diff options
Diffstat (limited to 'kregexpeditor')
169 files changed, 18002 insertions, 0 deletions
diff --git a/kregexpeditor/Comments b/kregexpeditor/Comments new file mode 100644 index 0000000..71f4470 --- /dev/null +++ b/kregexpeditor/Comments @@ -0,0 +1,4 @@ +(1) If I do not resize the widget to be reparented then it will take up all + the size of its new parent, and the parent will never receive a + repaint event, and will thus never get a chance to resize its new child + to a proper size (This is namely done in repaintEvent() ). diff --git a/kregexpeditor/KMultiFormListBox/Makefile.am b/kregexpeditor/KMultiFormListBox/Makefile.am new file mode 100644 index 0000000..5ee885f --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/Makefile.am @@ -0,0 +1,15 @@ +AM_CPPFLAGS = -DQT_NO_CAST_ASCII +noinst_LTLIBRARIES = libkmultiformlistbox.la + +INCLUDES= -I$(srcdir)/../KWidgetStreamer $(all_includes) + +include_HEADERS = kmultiformlistboxentry.h kmultiformlistbox.h \ + kmultiformlistboxfactory.h +noinst_HEADERS = ccp.h indexWindow.h kmultiformlistbox-multivisible.h \ + kmultiformlistbox-windowed.h widgetwindow.h windowlistboxitem.h +libkmultiformlistbox_la_SOURCES = ccp.cpp kmultiformlistboxentry.cpp \ + kmultiformlistbox.cpp kmultiformlistbox-multivisible.cpp \ + kmultiformlistboxfactory.cpp indexWindow.cpp \ + kmultiformlistbox-windowed.cpp widgetwindow.cpp windowlistboxitem.cpp + +METASOURCES = AUTO diff --git a/kregexpeditor/KMultiFormListBox/TODO b/kregexpeditor/KMultiFormListBox/TODO new file mode 100644 index 0000000..0c20864 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/TODO @@ -0,0 +1 @@ +- cut/copy/paste should place/read data from the system clipboard. diff --git a/kregexpeditor/KMultiFormListBox/ccp.cpp b/kregexpeditor/KMultiFormListBox/ccp.cpp new file mode 100644 index 0000000..d64a3b2 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/ccp.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +//--------------------- +// ccp = Cut-Copy-Paste +//--------------------- + +#include "kmultiformlistbox-multivisible.h" +#include "ccp.h" +#include <qobjectlist.h> +#include <qpopupmenu.h> +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> +#endif + +CCP::CCP(KMultiFormListBoxMultiVisible *ee_, KMultiFormListBoxEntry *eee_) : QObject() { + ee = ee_; + eee = eee_; + install(eee); +} + +void CCP::install(QObject *elm) +{ + elm->installEventFilter(this); + const QObjectList *children = elm->children(); + if (children) { + QObjectListIt it = QObjectListIt(*children); + + while (QObject *child=it.current()) { + if (child->inherits("KMultiFormListBoxMultiVisible")) { + // Stop if the widget is an KMultiFormListBox, as this widget has its own cut/copy/paste + } + else { + install(child); + } + ++it; + } + } +} + +// This function post the Cut/Copy/Paste menu +bool CCP::eventFilter(QObject *, QEvent *event) +{ + if (event->type() != QEvent::MouseButtonPress || + ((QMouseEvent *) event)->button() != RightButton || + ((QMouseEvent *) event)->state() != QEvent::ControlButton) { + return false; + } + + QPoint pos = ((QMouseEvent *) event)->globalPos(); + + QPopupMenu *menu = new QPopupMenu(); + menu->insertItem(i18n("Cut"),1); + menu->insertItem(i18n("Copy"),2); + menu->insertItem(i18n("Paste"),3); + menu->insertItem(i18n("Insert Blank"),4); + + int res=menu->exec(pos); + switch (res) { + case 1: ee->cut(eee); break; + case 2: ee->copy(eee); break; + case 3: ee->paste(eee); break; + case 4: ee->addElement(eee); break; + } + return true; +} + diff --git a/kregexpeditor/KMultiFormListBox/ccp.h b/kregexpeditor/KMultiFormListBox/ccp.h new file mode 100644 index 0000000..41857a5 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/ccp.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __ccp +#define __ccp + + +/** + Helper class for @ref KMultiFormListBoxMultiVisible which is used to install EventFilters. + + When the user presses CTRL + right mouse button then a menu should + appear which offers him cut and paste capabilities for the entries in + the KMultiFormListBoxMultiVisible. + + To obtain this an event filter must be install for each subwidget of the + KMultiFormListBoxMultiVisible. This event filter must catch the right mouse press event and + post the menu. This requires a widget which has the method @ref + eventFilter defined. We have this helper class exactly for this purpose. + + For each @ref KMultiFormListBoxEntry in the @ref KMultiFormListBoxMultiVisible widget an instance of + this class is associated. + + CCP stand for Cut Copy and Paste + + @internal +**/ +class CCP :public QObject { + +private: + friend class KMultiFormListBoxMultiVisible; + /** + * Constructor is private so only the class @ref KMultiFormListBoxMultiVisible may create an + * instance of this widget. + **/ + CCP(KMultiFormListBoxMultiVisible *,KMultiFormListBoxEntry *); + + void install(QObject *); + bool eventFilter(QObject *, QEvent *); + + // Instance variables. + + KMultiFormListBoxMultiVisible *ee; + KMultiFormListBoxEntry *eee; +}; + +#endif /* ccp */ + diff --git a/kregexpeditor/KMultiFormListBox/idx.xbm b/kregexpeditor/KMultiFormListBox/idx.xbm new file mode 100644 index 0000000..e51baee --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/idx.xbm @@ -0,0 +1,5 @@ +#define idx_width 16 +#define idx_height 12 +static char idx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x04, 0x02, 0x04, 0x02, 0xc4, 0x8a, + 0x24, 0x53, 0x14, 0x22, 0x14, 0x22, 0x24, 0x53, 0xce, 0x8a, 0x00, 0x00}; diff --git a/kregexpeditor/KMultiFormListBox/indexWindow.cpp b/kregexpeditor/KMultiFormListBox/indexWindow.cpp new file mode 100644 index 0000000..362d012 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/indexWindow.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include "indexWindow.moc" +#endif + +#include "indexWindow.h" +#include <iostream> +#include <qlayout.h> + +indexWindow::indexWindow() : QWidget(0,"", WStyle_Customize | WType_Popup) +{ + lb = new QListBox(this); + connect(lb,SIGNAL(selected(int)), this, SLOT(lbSelected(int))); + QHBoxLayout *lay = new QHBoxLayout(this); + lay->addWidget(lb); + lbFinish = false; +} + +void indexWindow::lbSelected(int index) +{ + lbFinish = true; + hide(); + lbFinish = false; + finish(index); +} + +void indexWindow::finish(int index) +{ + itemSelected = index; + qApp->exit_loop(); +} + + +void indexWindow::insertItem(QString txt) +{ + lb->insertItem(txt); +} + +void indexWindow::hideEvent(QHideEvent *h) +{ + QWidget::hideEvent(h); + if (!lbFinish) + finish(-1); +} + + +int indexWindow::exec(const QPoint & /*start*/, int /*width*/) +{ + // This code is not xinerama safe, on the other hand this part of the widget + // is not used in KRegExpEditor. This is part of a widget which has + // never been completed, but which is used partly by KRegExpEditor. + // 23 Feb. 2003 11:28 -- Jesper K. Pedersen +/* + // calculate the height of all the elements together. + // I need to do it this way, as sizeHint doesn't report the correct size + // and itemHeight doesn't neither. + int elm_h = lb->item(0)->height(lb) * lb->count(); + elm_h += 2*lb->frameWidth(); + + QWidget *desktop = QApplication::desktop(); + int desktop_h = desktop->height(); + int rest_h = desktop_h - start.y(); + int below_h = QMAX(rest_h, 200); + + int start_y = start.y(); + + if (rest_h < 200 && elm_h > 200) { + start_y = desktop_h-QMIN(elm_h,200); + } + + setGeometry(start.x(), start_y, width, QMIN(elm_h, below_h)); + show(); + qApp->enter_loop(); + return itemSelected; +*/ + return 0; +} + diff --git a/kregexpeditor/KMultiFormListBox/indexWindow.h b/kregexpeditor/KMultiFormListBox/indexWindow.h new file mode 100644 index 0000000..3597960 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/indexWindow.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __indexWindow +#define __indexWindow + +#include <qlistbox.h> + +/** + Post a toplevel listbox synchronously. + + When the user presses the Idx button in the @ref KMultiFormListBox, then a + listbox with the elements from the KMultiFormListBox must be shown. From this + listbox the user should chose the element he wants to scroll to. + This widget takes care of posting this listbox, and ensuring that the + user can not do anything else before he has chosen an element. + + This widget resembles the behavior of @ref QPopupMenu, the difference + is, however, that the QPopupMenu can not handle that the elements in the + menu exceed the size of the screen. This widget can. + + In the future this widget may be replaced with the QPopupMenu if the + QPopupMenu can handle this situation. But for now - it works! + + @internal +**/ +class indexWindow : public QWidget{ + +Q_OBJECT + +public: + indexWindow(); + + /** + This method inserts an element into the listbox which is shown when + the @ref exec method is invoked. + **/ + void insertItem(QString txt); + + /** + This function shows the index window with the elements inserted using + the @ref insertItem function. The function will not return before the + user has chosen an element in the listbox, or have pressed the right + mouse button outside the window. As a result of returning from this + function, the listbox is hidden. + + @param start The upper left corner of the pop-up window. + @param width The width of the window + @return The index of the element chosen, or -1 if no element has been + chosen. + **/ + int exec(const QPoint &start, int width); + +protected: + void finish(int retVal); + virtual void hideEvent(QHideEvent *h); + +protected slots: + void lbSelected(int); + +private: + QListBox *lb; + bool lbFinish; + int itemSelected; + +}; + +#endif /* indexWindow */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.cpp new file mode 100644 index 0000000..335863b --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include <qmessagebox.h> +#else + #include <kmessagebox.h> + #include "kmultiformlistbox-multivisible.moc" +#endif + +#include "kmultiformlistbox-multivisible.h" +#include "indexWindow.h" +#include "ccp.h" + +#include <qbitmap.h> + +const int indexButtonWidth = 16; +const int indexButtonHeight = 12; +const uchar indexButtonBits[] = { + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x04, 0x02, 0x04, 0x02, 0xc4, 0x8a, + 0x24, 0x53, 0x14, 0x22, 0x14, 0x22, 0x24, 0x53, 0xce, 0x8a, 0x00, 0x00 +}; + + +KMultiFormListBoxMultiVisible::KMultiFormListBoxMultiVisible(KMultiFormListBoxFactory *fact, QWidget *parent, const char *name) + : QScrollView(parent, name) +{ + factory = fact; + + // Initialize the element list + elms = new WidgetList(); + + // Initialize the clipper. + enableClipper(true); + resizeContents(50,50); // This is required for proper functionality +} + + + +//---------------------------------------------------------------------- +// This function returns a list of the elements in the KMultiFormListBox widget. +//---------------------------------------------------------------------- +KMultiFormListBoxEntryList KMultiFormListBoxMultiVisible::elements() +{ + KMultiFormListBoxEntryList res; + for (QWidget *child = elms->first(); child; child=elms->next()) { + if (strcmp(child->name(),"seperator") != 0) { + res.append((KMultiFormListBoxEntry *) child); + } + } + return res; +} + + +//---------------------------------------------------------------------- +// This function is called whenever the KMultiFormListBox widget is resized. It is +// necessary to ensure that the content of the clipper is resized. +//---------------------------------------------------------------------- +void KMultiFormListBoxMultiVisible::resizeEvent(QResizeEvent *e) +{ + // The call of the super class ensures that the outer border is updated. + QScrollView::resizeEvent(e); + + updateClipperContent(); +} + +void KMultiFormListBoxMultiVisible::updateClipperContent() +{ + // Extract the current size of the clipper + int ClipperWidth = clipper()->size().width(); + int ClipperHeight = clipper()->size().height(); + + // Initialize the calculation of the size of the new clipper. + int totalHeight = 0; + int maxWidth = ClipperWidth; + int count = 0; + + + // calculate the required size. + for (QWidget *child = elms->first(); child; child=elms->next()) { + maxWidth = QMAX(maxWidth, child->sizeHint().width()); + if (strcmp(child->name(), "seperator") != 0) { + totalHeight += child->sizeHint().height(); + count++; + } + else { + totalHeight += child->size().height(); + } + } + + // Calculate the extra height for the elements. + int extra = 0; + if (totalHeight < ClipperHeight && count != 0) { + extra = (ClipperHeight - totalHeight) / count; + totalHeight = ClipperHeight; + } + + // Now place the elements in the clipper. + int yPos = 0; + for (QWidget *child2 = elms->first(); child2; child2=elms->next()) { + int h; + if ( strcmp(child2->name(),"seperator") != 0) { + h = child2->sizeHint().height(); + h += extra; + } + else { + h = child2->size().height(); + } + + moveChild(child2, 0,yPos); + + child2->resize(maxWidth,h); + yPos += h; + } + + // Finally call the resize procedure for the clipper to ensure that the + // new sizes is shown properly. + resizeContents(maxWidth, totalHeight); +} + + +void KMultiFormListBoxMultiVisible::addElement() +{ + addElement(0); +} + +void KMultiFormListBoxMultiVisible::addElement(KMultiFormListBoxEntry *after) +{ + KMultiFormListBoxEntry *elm = factory->create(viewport()); + insertElmIntoWidget(elm, after); +} + +void KMultiFormListBoxMultiVisible::append(KMultiFormListBoxEntry *elm) +{ + elm->reparent(viewport(), 0, QPoint(0,0), false); + insertElmIntoWidget(elm, 0); +} + +void KMultiFormListBoxMultiVisible::delElement(QWidget *elm) +{ + int index = elms->find(elm); + QWidget *next = elms->at(index+1); + if (strcmp(next->name(),"seperator") != 0) { + elms->removeRef(next); + removeChild(next); + } + + elms->removeRef(elm); + removeChild(elm); + + updateClipperContent(); +} + +void KMultiFormListBoxMultiVisible::delAnElement() +{ + delElement(elms->at(0)); +} + +void KMultiFormListBoxMultiVisible::insertElmIntoWidget(KMultiFormListBoxEntry *elm, KMultiFormListBoxEntry *after) +{ + // Bind the index button if it exists. + if (elm->indexButton()) { + elm->indexButton()->setPixmap(QBitmap(indexButtonWidth, indexButtonHeight, + indexButtonBits, true)); + connect(elm->indexButton(), SIGNAL(clicked()), elm, SLOT(acceptIndexButton())); + connect(elm, SIGNAL(gotoIndex(KMultiFormListBoxEntry *)), + this, SLOT(showIndexList(KMultiFormListBoxEntry *))); + } + + // Find the location to insert the new element. + int index = elms->count(); + if (after) { + index = elms->findRef(after); + } + + // Now show the new element. + elms->insert(index, elm); + elm->show(); + addChild(elm,0,0); // updateClipperContent will place the child correctly. + + QWidget *sep = factory->separator(viewport()); + if (sep != 0) { + sep->setName("seperator"); + sep->show(); + addChild(sep,0,0); // updateClipperContent will place the child correctly. + elms->insert(index+1, sep); + } + + updateClipperContent(); + + showWidget(elm); // scroll to show the new widget. + + // install cut'n'paste functionallity + new CCP(this,elm); +} + + +//---------------------------------------------------------------------- +// This function shows the list of available Idx elements. +//---------------------------------------------------------------------- +void KMultiFormListBoxMultiVisible::showIndexList(KMultiFormListBoxEntry *elm) +{ + indexWindow *menu = new indexWindow(); + + // Insert the elements into the menu item. + for (QWidget *child = elms->first(); child; child=elms->next()) { + if ( strcmp(child->name(), "seperator") != 0) { + QString txt = ((KMultiFormListBoxEntry *) child)->idxString(); + menu->insertItem(txt); + } + } + + // Calculate the location of the window + QPoint start; + int width; + elm->indexWindowPos(&start, &width); + + // Show the window. + int index = menu->exec(start,width); + + if (index != -1) { + for (QWidget *child = elms->first(); child; child=elms->next()) { + if ( strcmp(child->name(), "seperator") != 0) { + + if (index == 0) { + showWidget((KMultiFormListBoxEntry *) child); + break; + } + index--; + } + } + } + delete menu; +} + +//---------------------------------------------------------------------- +// Scroll to the loaction of the given KMultiFormListBoxEntry element. +//---------------------------------------------------------------------- +void KMultiFormListBoxMultiVisible::showWidget(KMultiFormListBoxEntry *elm) +{ + setContentsPos(childX(elm), childY(elm)); +} + + +void KMultiFormListBoxMultiVisible::cut(KMultiFormListBoxEntry *elm) +{ + if (countElements(elms) == 1) { + KMessageBox::information(this, i18n("Due to a bug, it is not possible to remove the last element."), i18n("Internal Error") ); + return; + } + + QDataStream stream(clipboard, IO_WriteOnly); + factory->toStream( elm, stream ); + delElement(elm); +} + +void KMultiFormListBoxMultiVisible::copy(KMultiFormListBoxEntry *elm) +{ + QDataStream stream(clipboard, IO_WriteOnly); + factory->toStream(elm, stream); +} + +void KMultiFormListBoxMultiVisible::paste(KMultiFormListBoxEntry *oldElm) +{ + if (clipboard.size() == 0) { + KMessageBox::information(this, i18n("There is no element on the clipboard to paste in.")); + return; + } + + KMultiFormListBoxEntry *newElm = factory->create(viewport()); + QDataStream stream( clipboard, IO_ReadOnly ); + factory->fromStream(stream, newElm); + insertElmIntoWidget(newElm,oldElm); +} + + +int KMultiFormListBoxMultiVisible::countElements(WidgetList *elms) +{ + int count = 0; + + for (QWidget *child = elms->first(); child; child=elms->next()) { + if (dynamic_cast<const KMultiFormListBoxEntry *>(child)) + count++; + } + + return count; +} + + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.h new file mode 100644 index 0000000..87aeba4 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +// ------------------------------- Description ---------------------------- +// This is the KMultiFormListBox Widget. You do not need to inheret from this class, +// your interface to it will be through the methods `append` and `elements'. +// +// To make an instance of the widget, you need to inherit the classes +// `KMultiFormListBoxFactory' and `KMultiFormListBoxEntry'. +// ------------------------------------------------------------------------ +#ifndef __kmultiformlistboxmultivisble +#define __kmultiformlistboxmultivisble + +// -------------------------------- includes ------------------------------ +#include "kmultiformlistbox.h" +//------------------------------------------------------------------------- + +/** + @internal +*/ +class KMultiFormListBoxMultiVisible :public QScrollView, KMultiFormListBoxShower { + +Q_OBJECT + +friend class KMultiFormListBox; + +private: + /** + @param factory A factory used to generate the instances of KMultiFormListBoxEntry + class which is repeated in the KMultiFormListBox + @param parent A pointer to the parent widget + */ + KMultiFormListBoxMultiVisible(KMultiFormListBoxFactory *factory, QWidget *parent = 0, const char *name = 0); + + /** + @return The elements in the KMultiFormListBox + */ + KMultiFormListBoxEntryList elements(); + void append(KMultiFormListBoxEntry *); + + QWidget* qWidget() { return this; } + + +public slots: + + /** + This slot should be connected to a button which lets the user know that + he may get more elements in this KMultiFormListBox by pressing it. + The button should be labeled ``More Entries'' or something similar. + */ + void addElement(); // Adds an empty element to the KMultiFormListBox + + +protected slots: + + /** + When this slot is invoked then the Idx menu will be shown. + @param elm The KMultiFormListBoxEntry element where the Idx button was + pressed. This information is necessary to be able to calculate the + location where the drop down menu should be shown + */ + void showIndexList(KMultiFormListBoxEntry *elm); + +protected: + /** + Copies the element pointed to by which to the clipboard and removes it + from the interface. + This function is accessed from the class @ref CCP. + @param which A pointer to the element to cut. + */ + void cut(KMultiFormListBoxEntry *which); + + /** + Copies the element pointed to by which to the clipboard. + This function is accessed from the class @ref CCP. + @param which A pointer to the element to copied. + */ + void copy(KMultiFormListBoxEntry *which); + + /** + Paste the element from the clipboard to the KMultiFormListBox + This function is accessed from the class @ref CCP. + @param which A pointer to the KMultiFormListBoxEntry element which the + clipboard element should be inserted before,. + */ + void paste(KMultiFormListBoxEntry *which); + + /** + Inserts an empty KMultiFormListBoxEntry into the widget. + @param which A pointer to the element which the new empty widget + should be inserted before. + */ + + void addElement(KMultiFormListBoxEntry *); + + friend class CCP; + + virtual void resizeEvent(QResizeEvent *); + void addElemBefore(KMultiFormListBoxEntry *newElm, QWidget *existing); + void insertElmIntoWidget(KMultiFormListBoxEntry *elm, KMultiFormListBoxEntry *after); + void showWidget(KMultiFormListBoxEntry *elm); + void delElement(QWidget *); + void delAnElement(); + void addElemBefore(KMultiFormListBoxEntry *newElm, KMultiFormListBoxEntry *existing); + void updateClipperContent(); + int countElements(WidgetList *); + + + +private: + // Instance variables + + KMultiFormListBoxFactory *factory; + WidgetList *elms; + QPushButton *addBut; + QByteArray clipboard; +}; + + +#endif /* kmultiformlistboxmultivisble */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-shower.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-shower.h new file mode 100644 index 0000000..fe786d7 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-shower.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistboxshower +#define __kmultiformlistboxshower + +// -------------------------------- includes ------------------------------ +//------------------------------------------------------------------------- +typedef QPtrList<KMultiFormListBoxEntry> KMultiFormListBoxEntryList ; + +/** + Abstract class defining the interface for widgets showing a number of @ref KMultiFormListBoxEntry. + + @internal +*/ +class KMultiFormListBoxShower { + +public: + virtual KMultiFormListBoxEntryList elements() = 0; + + /** Appends the given argument to the list */ + virtual void append(KMultiFormListBoxEntry *) = 0; + + /** Return the element as a QWidget */ + virtual QWidget* qWidget() = 0; + + /** Adds an empty element. */ + virtual void addElement() = 0; + + /** Deletes an element at the given index. */ + virtual void delElement(QWidget *) = 0; + + /** Deletes any element from the list */ + virtual void delAnElement() = 0; +}; + + +#endif /* kmultiformlistboxshower */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.cpp new file mode 100644 index 0000000..6ef14d3 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <kmessagebox.h> + #include <kpushbutton.h> + #include <kstdguiitem.h> + #include "kmultiformlistbox-windowed.moc" +#endif + +#include "widgetwindow.h" +#include "windowlistboxitem.h" + +KMultiFormListBoxWindowed::KMultiFormListBoxWindowed(KMultiFormListBoxFactory *factory, QWidget *parent, + bool showUpDownButtons, bool showHelpButton, + QString addButtonText,const char *name) + : QWidget( parent, name ) +{ + _layout = new QVBoxLayout(this); + + QHBoxLayout *innerLayout = new QHBoxLayout(); + _layout->addLayout(innerLayout); + + _listbox = new KListBox(this,"listbox"); + _listbox->setSelectionMode(QListBox::Single); + innerLayout->addWidget(_listbox); + + QVBoxLayout *buttons = new QVBoxLayout(); + innerLayout->addLayout(buttons); + + QPushButton *but = new QPushButton(addButtonText, this,"Add Button"); + buttons->addWidget(but,0); + connect(but, SIGNAL(clicked()), this, SLOT(addNewElement())); + + but = new QPushButton(i18n("Edit"), this,"Edit Button"); + buttons->addWidget(but,0); + connect(but,SIGNAL(clicked()), this, SLOT(slotEditSelected())); + connect(_listbox, SIGNAL(doubleClicked(QListBoxItem *)), this, SLOT(slotEditSelected(QListBoxItem *))); + _buttonList.append(but); + + but = new QPushButton(i18n("Delete"), this, "Delete Button"); + buttons->addWidget(but,0); + connect(but, SIGNAL(clicked()), this, SLOT(slotDeleteEntry())); + _buttonList.append(but); + + but = new QPushButton(i18n("Copy"), this, "Copy Button"); + buttons->addWidget(but,0); + connect(but, SIGNAL(clicked()), this, SLOT(slotCopySelected())); + _buttonList.append(but); + + if (showUpDownButtons) { + but = new QPushButton(i18n("Up"), this, "Up Button"); + buttons->addWidget(but, 0); + connect(but, SIGNAL(clicked()), this, SLOT(slotMoveItemUp())); + _buttonList.append(but); + + but = new QPushButton(i18n("Down"), this, "Down Button"); + buttons->addWidget(but, 0); + connect(but, SIGNAL(clicked()), this, SLOT(slotMoveItemDown())); + _buttonList.append(but); + } + + if (showHelpButton) { + but = new KPushButton(KStdGuiItem::help(), this, "Help Button"); + buttons->addWidget(but, 0); + connect(but, SIGNAL(clicked()), this, SIGNAL(showHelp())); + } + + buttons->addStretch(1); + _factory = factory; + slotUpdateButtonState(); + +} + +KMultiFormListBoxEntryList KMultiFormListBoxWindowed::elements() +{ + KMultiFormListBoxEntryList list; + for (unsigned int i=0; i < _listbox->count(); i++) { + WindowListboxItem *item = (WindowListboxItem *) _listbox->item(i); + list.append(item->entry()); + } + return list; +} + +void KMultiFormListBoxWindowed::delElement(QWidget */*elm*/) +{ + // kdDebug() << "KMultiFormListBoxWindowed::delElement NOT YET IMPLEMENTED"<<endl; + // TODO +} + +void KMultiFormListBoxWindowed::delAnElement() +{ + // kdDebug() << "KMultiFormListBoxWindowed::delAnElement NOT YET IMPLEMENTED"<<endl; + // TODO +} + + +void KMultiFormListBoxWindowed::append(KMultiFormListBoxEntry *elm) +{ + (void) new WidgetWindow(_factory, elm, _listbox); + slotUpdateButtonState(); +} + +void KMultiFormListBoxWindowed::addNewElement() +{ + // kdDebug() << "addNewElement " << _factory << "," << _listbox << endl; + + QWidget *widget = new WidgetWindow(_factory, _listbox); + widget->show(); + connect(widget, SIGNAL(finished()), this, SLOT(slotUpdateButtonState())); +} + +void KMultiFormListBoxWindowed::addElement() +{ + new WidgetWindow(_factory, _listbox); + slotUpdateButtonState(); +} + +void KMultiFormListBoxWindowed::slotEditSelected(QListBoxItem *item) +{ + ((WindowListboxItem *) item)->displayWidget(); +} + +void KMultiFormListBoxWindowed::slotEditSelected() +{ + WindowListboxItem *item = selected(); + if (item) { + slotEditSelected(item); + } +} + +void KMultiFormListBoxWindowed::slotDeleteEntry() +{ + WindowListboxItem *item = selected(); + if (item) { + int answer = + KMessageBox::warningContinueCancel(0, i18n("Delete item \"%1\"?").arg(item->text()),i18n("Delete Item"),KStdGuiItem::del()); + if (answer == KMessageBox::Continue) { + delete item; + slotUpdateButtonState(); + } + } +} + +void KMultiFormListBoxWindowed::slotCopySelected() +{ + WindowListboxItem *item = selected(); + if (item) { + item->clone(); + } +} + +WindowListboxItem *KMultiFormListBoxWindowed::selected() +{ + int i = _listbox->currentItem(); + if (i == -1) { + return 0; + } else { + return (WindowListboxItem *) _listbox->item(i); + } +} + +void KMultiFormListBoxWindowed::slotMoveItemUp() +{ + WindowListboxItem *item = selected(); + if (item == 0) + return; + + int index = _listbox->index(item); + if (index != 0) { + _listbox->takeItem(item); + _listbox->insertItem(item, index-1); + _listbox->setCurrentItem(item); + } +} + +void KMultiFormListBoxWindowed::slotMoveItemDown() +{ + WindowListboxItem *item = selected(); + if (item == 0) + return; + + unsigned int index = _listbox->index(item); + if (index < _listbox->count()) { + _listbox->takeItem(item); + _listbox->insertItem(item, index+1); + _listbox->setCurrentItem(item); + } +} + +void KMultiFormListBoxWindowed::slotUpdateButtonState() +{ + bool on = (_listbox->count() != 0); + for (unsigned int i=0; i<_buttonList.count(); i++) { + _buttonList.at(i)->setEnabled(on); + } +} diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.h new file mode 100644 index 0000000..74d6d9f --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistboxwindowed +#define __kmultiformlistboxwindowed + +#ifdef QT_ONLY + #include "compat.h" + #include <qlistbox.h> +#else + #include <klistbox.h> +#endif + +#include "kmultiformlistboxfactory.h" +#include "kmultiformlistbox.h" +class WindowListboxItem; + + +/** + This class implements the windowed look for a @ref KMultiFormListBox + + @internal +*/ +class KMultiFormListBoxWindowed :public QWidget, KMultiFormListBoxShower { + +Q_OBJECT + +friend class KMultiFormListBox; + +private: + KMultiFormListBoxWindowed(KMultiFormListBoxFactory *factory, QWidget *parent, + bool showUpDownButtons, bool showHelpButton, QString addButtonText, + const char *name); + + KMultiFormListBoxEntryList elements(); + const KMultiFormListBoxEntryList elements() const; + void append(KMultiFormListBoxEntry *); + WindowListboxItem *selected(); + QWidget* qWidget() { return this; } + + QVBoxLayout* _layout; + KMultiFormListBoxFactory* _factory; + QPtrList<QPushButton> _buttonList; + KListBox* _listbox; + virtual void delElement(QWidget *); // Deletes the given element + virtual void delAnElement(); + void addElement(); + + +public slots: + void addNewElement(); + +signals: + void showHelp(); + +private slots: + void slotEditSelected(); + void slotEditSelected(QListBoxItem *item); + void slotCopySelected(); + void slotMoveItemUp(); + void slotMoveItemDown(); + void slotDeleteEntry(); + void slotUpdateButtonState(); + +}; + + +#endif /* kmultiformlistboxwindowed */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.cpp new file mode 100644 index 0000000..57b5abb --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "kmultiformlistbox.moc" +#endif + +#include "kmultiformlistbox-multivisible.h" +#include "kmultiformlistbox-windowed.h" + +KMultiFormListBox::KMultiFormListBox( KMultiFormListBoxFactory *factory, KMultiFormListBoxType tp, QWidget *parent, + bool showUpDownButtons, bool showHelpButton, QString addButtonText, + const char *name ) : QWidget( parent, name ) +{ + switch ( tp ) { + + case MultiVisible: + theWidget = new KMultiFormListBoxMultiVisible( factory, this, "KMultiFormListBox Widget" ); + break; + + case Windowed: + theWidget = new KMultiFormListBoxWindowed( factory, this, showUpDownButtons, + showHelpButton, addButtonText, "KMultiFormListBox Widget" ); + break; + } + + QWidget *widget = theWidget->qWidget(); + + QHBoxLayout *layout = new QHBoxLayout( this ); + _factory = factory; + layout->addWidget( widget ); +} + +void KMultiFormListBox::append( KMultiFormListBoxEntry *element ) +{ + theWidget->append( element ); +} + +void KMultiFormListBox::addElement() +{ + theWidget->addElement(); +} + +KMultiFormListBoxEntryList KMultiFormListBox::elements() +{ + return theWidget->elements(); +} + +const KMultiFormListBoxEntryList KMultiFormListBox::elements() const +{ + return const_cast<KMultiFormListBox*>(this)->elements(); +} + +void KMultiFormListBox::slotChangeFace( KMultiFormListBoxType /*newFace*/ ) +{ + // TODO + // kdDebug() << "It's not possible yet to change the face on the fly." << endl + // << "Please let me (blackie@kde.org) know that you need it, and I'll work on it" << endl; +} + +void KMultiFormListBox::toStream( QDataStream& stream ) const +{ + const KMultiFormListBoxEntryList elms = elements(); + stream << elms.count(); + for ( QPtrListIterator<KMultiFormListBoxEntry> it(elms); *it; ++it) + _factory->toStream( *it, stream ); +} + +void KMultiFormListBox::fromStream( QDataStream& stream ) +{ + unsigned int fromCount, toCount; + stream >> fromCount; + + toCount = elements().count(); + + // adds/remove elements in the to list, to make it have the correct length. + for (unsigned int j=toCount; j< fromCount; ++j) { + addElement(); + } + for (unsigned int k=fromCount; k < toCount; ++k) { + theWidget->delAnElement(); + } + + KMultiFormListBoxEntryList elms = elements(); + for (QPtrListIterator<KMultiFormListBoxEntry> it(elms); *it; ++it) + _factory->fromStream( stream, *it ); +} + + + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.h new file mode 100644 index 0000000..8e85808 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistbox +#define __kmultiformlistbox + +#include "kmultiformlistboxfactory.h" +#include "kmultiformlistbox-shower.h" +#include "kmultiformlistboxentry.h" +#include <qptrlist.h> +#include <qlayout.h> +#include <qscrollview.h> + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> +#endif + +class QDataStream; + + +typedef QPtrList<KMultiFormListBoxEntry> KMultiFormListBoxEntryList ; +typedef QPtrList<QWidget> WidgetList; +class KMultiFormListBoxMultiVisible; + +/** + The main class used to get an KMultiFormListBox widget. + + The KMultiFormListBox widget consist of a sub-widget which is repeated a + number of times, it is up to the end user to determine the number of times + the sub widget is repeated, and he may require an additional copy simply + by pressing a ``Add'' or ``More Entries'' button. The KMultiFormListBox + widget has two different faces (i.e. two different end user + interfaces). One (Windowed) will show a listbox from which the end user + can access each subwidget containing data by pressing the LMB on a name + for the element. The other face (MultiVisible) shows all the subwidgets in + one huge ``Listbox''. + + To use the KMultiFormListBox widget you must create a class which is inherited + from the @ref KMultiFormListBoxFactory class. This new class must override the + function `create'. This function must return a freshly made instance of + the class @ref KMultiFormListBoxEntry (or a subclass of this). The KMultiFormListBoxEntry + instance is the one inserted into the KMultiFormListBox widget (one instance for + each sub widget in the KMultiFormListBox widget). + + @author Jesper Kjær Pedersen <blackie@kde.org> + **/ +class KMultiFormListBox : public QWidget { + +Q_OBJECT + +public: + + enum KMultiFormListBoxType {MultiVisible, Windowed}; + + /** + @param factory A factory used to generate the instances of + KMultiFormListBoxEntry class which is repeated in the KMultiFormListBox + @param parent A pointer to the parent widget + **/ + KMultiFormListBox(KMultiFormListBoxFactory *factory, + KMultiFormListBoxType tp=Windowed, + QWidget *parent = 0, bool showUpDownButtons = true, + bool showHelpButton = true, QString addButtonText = i18n("Add"), + const char *name = 0); + + /** + @return The elements in the KMultiFormListBox. + **/ + KMultiFormListBoxEntryList elements(); + const KMultiFormListBoxEntryList elements() const; + + /** + TODO. + **/ + void append(KMultiFormListBoxEntry *); + + /** write data out to stream */ + void toStream( QDataStream& stream ) const; + + /** reads data in from stream */ + void fromStream( QDataStream& stream ); + +public slots: + + /** + Adds an empty element to the KMultiFormListBox. + + This slot is only required for the @ref MultiVisible face. It should + be connected to a button which lets the user know that he may get more + elements in this KMultiFormListBox by pressing it. The button should + be labeled ``More Entries'' or something similar. + **/ + void addElement(); // Adds an empty element to the KMultiFormListBox + + /** + Changes the face of the KMultiFormListBox. + @param face The new face of the KMultiFormListBox + **/ + void slotChangeFace(KMultiFormListBoxType newFace); + +private: + KMultiFormListBoxShower *theWidget; + KMultiFormListBoxFactory *_factory; + +}; + + +#endif /* kmultiformlistbox */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.cpp new file mode 100644 index 0000000..e6768a3 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QT_ONLY + #include "kmultiformlistboxentry.moc" +#endif + +#include "kmultiformlistboxentry.h" +//---------------------------------------------------------------------- +// This function is needed to signal which of the KMultiFormListBox entries +// the Idx button was invoked from. +//---------------------------------------------------------------------- +void KMultiFormListBoxEntry::acceptIndexButton() +{ + emit gotoIndex(this); +} + + +void KMultiFormListBoxEntry::indexWindowPos(QPoint *start, int *width) +{ + // Calculate the position of the value widgets left-buttom border + QPoint global_point = valueWidget()->mapToGlobal(QPoint(0,0)); + start->setX(global_point.x()); + start->setY(global_point.y() + valueWidget()->height()); + + // Calculate the width of the list. + global_point = indexButton()->mapToGlobal(QPoint(0,0)); + *width = global_point.x() + indexButton()->width() - start->x(); +} diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.h b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.h new file mode 100644 index 0000000..7937fe1 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistboxentry +#define __kmultiformlistboxentry + +#include <qpoint.h> +#include <qwidget.h> +#include <qpushbutton.h> + +/** + This widget must be the base class for an entry widget used in the @ref + KMultiFormListBox class. It is necessary for you to inherit this class to get any + information attached to the elements in the KMultiFormListBox. + + The KMultiFormListBox widget features a fast scrolling mechanism through the Idx + button. If you want to use this in you KMultiFormListBox, then you must do the + following: + @li Create a @ref QPushButton as a sub-widget to your KMultiFormListBoxEntry. + @li Override the @ref indexButton method to return your QPushButton + @li Override the @ref idxString to return a @ref QString + with a textual representation of the content in this KMultiFormListBoxEntry. This + string will be used in the drop-down box which the user gets when he + presses the Idx button. + @li The drop down window must be aligned horizontal to some widget + (which should be next to the Idx button, to ensure a good looking GUI. The + position of the drop down widget may be specified in two ways: (1) + override the @ref valueWidget method to return a widget, to align with + (that is the upper right corner of the drop down window will be the + same as the lower right corner of this widget) or (2) override the @ref + indexWindowPos method to return a start point for the drop down window and + a width. + **/ +class KMultiFormListBoxEntry : public QWidget +{ + Q_OBJECT + +public: + KMultiFormListBoxEntry(QWidget *parent, const char *name) : QWidget(parent,name) {} + + virtual QPushButton *indexButton() { return 0; } + virtual QWidget *valueWidget() { return 0; } + + virtual void indexWindowPos(QPoint *start, int *width); // both variables are return values. + + // This function must return a string representing the KMultiFormListBox. This is + // used when showing the fast-search menu available from the `Idx' button. + virtual QString idxString() { return QString::fromLatin1(""); } + +public slots: + void acceptIndexButton(); + +signals: + void gotoIndex(KMultiFormListBoxEntry *); + +}; + +#endif /* kmultiformlistboxentry */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.cpp new file mode 100644 index 0000000..89b5d74 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "kmultiformlistboxfactory.h" +#include <qframe.h> + +QWidget *KMultiFormListBoxFactory::separator(QWidget *parent) { + QFrame* sep = new QFrame( parent ); + sep->setFrameStyle( QFrame::HLine | QFrame::Sunken); + sep->setLineWidth(1); + return sep; +} diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.h b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.h new file mode 100644 index 0000000..13f6561 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +// -------------------------------- includes ------------------------------ +#ifndef __kmultiformlistboxfactory +#define __kmultiformlistboxfactory +#include <qobject.h> +#include "kwidgetstreamer.h" +class KMultiFormListBoxEntry; +//------------------------------------------------------------------------- + + +/** + Factory use to generate elements for the @ref KMultiFormListBox widget. + + To use an @ref KMultiFormListBox, one must inherit from the class KMultiFormListBoxFactory + and override the method @ref create. This method must return an empty + element for the KMultiFormListBox (that is an @ref KMultiFormListBoxEntry or a subclass of + it). + + If you dislike the default separator between each of the elements or + simply do not want a separator in the KMultiFormListBox, then you may override + the method @ref separator. +**/ +class KMultiFormListBoxFactory : public KWidgetStreamer +{ +public: + virtual ~KMultiFormListBoxFactory() {} + + /** + This method must be overridden in subclasses and must return an + ``empty'' instance of the @ref KMultiFormListBoxEntry class, or perhaps rather + a subclass of this class. This instance will be owned by the caller of + this function. + + @param parent A pointer to the parent of this KMultiFormListBoxEntry widget + returned. + @return A fresh @ref KMultiFormListBoxEntry to be used in an instance of the + @ref KMultiFormListBox class. + **/ + virtual KMultiFormListBoxEntry *create(QWidget *parent) = 0; + + /** + This method is used to get a separator between the elements in an @ref + KMultiFormListBox. The widget returned from this method will be owned by the + caller. + + @param parent A pointer to the parent of the QWidget returned. + @return A widget which must be used as a separator between the @ref + KMultiFormListBoxEntry elements in an @ref KMultiFormListBox. + **/ + virtual QWidget *separator(QWidget *parent); +}; + +#endif /* kmultiformlistbox */ + diff --git a/kregexpeditor/KMultiFormListBox/widgetwindow.cpp b/kregexpeditor/KMultiFormListBox/widgetwindow.cpp new file mode 100644 index 0000000..022e452 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/widgetwindow.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "widgetwindow.h" +#include "windowlistboxitem.h" +#include <iostream> + +WidgetWindow::WidgetWindow(KMultiFormListBoxFactory *factory, KListBox *lb) + :KDialogBase(Plain, i18n("Widget Configuration"), Ok | Cancel, Ok, 0, "ConfigWindow", false) +{ + init(factory, lb); +} + +WidgetWindow::WidgetWindow(KMultiFormListBoxFactory *factory, KMultiFormListBoxEntry *widget, KListBox *lb) + :KDialogBase(Plain, i18n("Widget Configuration"), Ok | Cancel, Ok, 0, "ConfigWindow", false) +{ + init(factory, lb, widget); +} + +void WidgetWindow::init(KMultiFormListBoxFactory *factory, KListBox *lb, KMultiFormListBoxEntry *widget) +{ + listbox = lb; + myFact = factory; + + QFrame *frame = plainPage(); + QHBoxLayout *lay = new QHBoxLayout(frame,0,-1,"WidgetWindow::init::lay"); + + if (widget != 0) { + myWidget = widget; + widget->reparent(frame, 0, QPoint(0,0)); + } + else { + myWidget = factory->create(frame); + } + QDataStream stream( _backup, IO_WriteOnly ); + myFact->toStream( myWidget, stream ); + + lay->addWidget(myWidget); + + if (widget != 0) { + initialShow = false; + myListboxItem = new WindowListboxItem(listbox,myWidget->idxString(), this); + } + else { + initialShow = true; + } +} + + + +WidgetWindow::~WidgetWindow() +{ + delete myWidget; +} + +void WidgetWindow::slotOk() +{ + if (initialShow) { + myListboxItem = new WindowListboxItem(listbox,myWidget->idxString(), this); + } + else { + myListboxItem->setText(myWidget->idxString()); + } + initialShow = false; + KDialogBase::slotOk(); +} + +void WidgetWindow::slotCancel() +{ + if (initialShow) { + deleteLater(); + } + else { + QDataStream stream( _backup, IO_ReadOnly ); + myFact->fromStream( stream, myWidget ); + } + KDialogBase::slotCancel(); +} + +WidgetWindow *WidgetWindow::clone() +{ + WidgetWindow *item = new WidgetWindow(myFact, listbox); + QByteArray data; + QDataStream ws( data, IO_WriteOnly ); + myFact->toStream( myWidget, ws ); + QDataStream rs( data, IO_ReadOnly ); + myFact->fromStream( rs, item->myWidget ); + + item->slotOk(); + return item; +} + +void WidgetWindow::display() +{ + QDataStream stream( _backup, IO_WriteOnly); + myFact->toStream( myWidget, stream ); + show(); +} + +KMultiFormListBoxEntry *WidgetWindow::entry() +{ + return myWidget; +} diff --git a/kregexpeditor/KMultiFormListBox/widgetwindow.h b/kregexpeditor/KMultiFormListBox/widgetwindow.h new file mode 100644 index 0000000..f81b359 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/widgetwindow.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __configwindow +#define __configwindow + +#ifdef QT_ONLY + #include "compat.h" + #include <qlistbox.h> +#else + #include <kdialogbase.h> + #include <klistbox.h> +#endif + +#include "kmultiformlistbox-windowed.h" + +/** + @internal +*/ +class WidgetWindow :public KDialogBase +{ + friend class KMultiFormListBoxWindowed; + friend class WindowListboxItem; + + WidgetWindow(KMultiFormListBoxFactory *, KListBox *); + WidgetWindow(KMultiFormListBoxFactory *, KMultiFormListBoxEntry *widget, KListBox *); + void init(KMultiFormListBoxFactory *, KListBox *, KMultiFormListBoxEntry *widget = 0); + void display(); + KMultiFormListBoxEntry *entry(); + WidgetWindow *clone(); + ~WidgetWindow(); + +protected slots: + void slotOk(); + void slotCancel(); + +private: + KMultiFormListBoxFactory *myFact; + KMultiFormListBoxEntry *myWidget; + QByteArray _backup; + KListBox *listbox; + WindowListboxItem *myListboxItem; + bool initialShow; +}; + +#endif // configwindow diff --git a/kregexpeditor/KMultiFormListBox/windowlistboxitem.cpp b/kregexpeditor/KMultiFormListBox/windowlistboxitem.cpp new file mode 100644 index 0000000..41f9e5b --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/windowlistboxitem.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "windowlistboxitem.h" +#include "widgetwindow.h" + +WindowListboxItem::WindowListboxItem(QListBox *lb, QString text, WidgetWindow *windowWidget) + :QListBoxText(lb, text), myItem(windowWidget) +{ +} + +WindowListboxItem::~WindowListboxItem() +{ + delete myItem; +} + +void WindowListboxItem::displayWidget() +{ + myItem->display(); +} + +void WindowListboxItem::clone() +{ + myItem->clone(); +} + +KMultiFormListBoxEntry *WindowListboxItem::entry() +{ + return myItem->entry(); +} + diff --git a/kregexpeditor/KMultiFormListBox/windowlistboxitem.h b/kregexpeditor/KMultiFormListBox/windowlistboxitem.h new file mode 100644 index 0000000..2505b88 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/windowlistboxitem.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __windowlistboxitem +#define __windowlistboxitem +#include <qlistbox.h> +class WidgetWindow; +class KMultiFormListBoxWindowed; +class KMultiFormListBoxEntry; + + +/** + @internal +*/ +class WindowListboxItem :public QListBoxText +{ + friend class WidgetWindow; + friend class KMultiFormListBoxWindowed; +public: + WindowListboxItem(QListBox *, QString, WidgetWindow *); + ~WindowListboxItem(); + void clone(); + void displayWidget(); + KMultiFormListBoxEntry *entry(); + +private: + WidgetWindow *myItem; +}; + +#endif // __windowlistboxitem diff --git a/kregexpeditor/KWidgetStreamer/Makefile.am b/kregexpeditor/KWidgetStreamer/Makefile.am new file mode 100644 index 0000000..c9b1260 --- /dev/null +++ b/kregexpeditor/KWidgetStreamer/Makefile.am @@ -0,0 +1,9 @@ +AM_CPPFLAGS = -DQT_NO_CAST_ASCII +noinst_LTLIBRARIES = libkwidgetstreamer.la + +INCLUDES= -I$(srcdir)/../KMultiFormListBox $(all_includes) + +include_HEADERS = kwidgetstreamer.h +libkwidgetstreamer_la_SOURCES = kwidgetstreamer.cpp + +METASOURCES = AUTO diff --git a/kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp new file mode 100644 index 0000000..e91813a --- /dev/null +++ b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "kwidgetstreamer.h" +#include "kmultiformlistbox.h" +#include <qobjectlist.h> +#include <qvariant.h> + + +void KWidgetStreamer::toStream(const QObject* from, QDataStream& stream ) +{ + if ( from->inherits("KMultiFormListBox") ) { + // Hmm, we'll trust Qt that this dynamic_cast won't fail! + dynamic_cast<const KMultiFormListBox*>(from)->toStream( stream ); + } + + propertyToStream( from, stream ); +} + +void KWidgetStreamer::fromStream( QDataStream& stream, QObject* to ) +{ + if ( to->inherits("KMultiFormListBox") ) { + // Hmm, we'll trust Qt that this dynamic_cast won't fail! + dynamic_cast<KMultiFormListBox*>(to)->fromStream( stream ); + } + + propertyFromStream( stream, to ); +} + + +void KWidgetStreamer::propertyToStream( const QObject* from, QDataStream& stream ) +{ + // Only handle widgets. Alternatives to widgets are layouts, validators, timers, etc. + if ( ! from->inherits("QWidget") ) + return; + + // Serializing all the children (if any). + const QObjectList* children = from->children(); + if ( children ) { + stream << children->count(); + for ( QObjectListIt it = QObjectListIt(*children); *it; ++it ) { + toStream( *it, stream ); + } + } + else { + stream << (unsigned int) 0; + } + + // Now stream out properties + for ( PropertyMapIt mapIt = _map.begin(); mapIt != _map.end(); mapIt++ ) { + QString tp = mapIt.key(); + PropertyList list = mapIt.data(); + if ( from->inherits( tp.latin1() ) ) { + for ( PropertyListIt it = list.begin(); it != list.end(); ++it ) { + QVariant prop = from->property( (*it).latin1() ); + if ( ! prop.isValid() ) + qWarning("Invalid property: %s:%s", tp.latin1(), (*it).latin1() ); + + stream << prop ; + } + } + } +} + + +void KWidgetStreamer::propertyFromStream( QDataStream& stream, QObject* to ) +{ + // Only handle widgets. Alternatives to widgets are layouts, validators, timers, etc. + if ( ! to->inherits("QWidget") ) + return; + + // Stream in all the children (if any) + const QObjectList* children = to->children(); + unsigned int count; + + stream >> count; + if ( children ) { + Q_ASSERT( count == children->count() ); + for ( QObjectListIt it = QObjectListIt(*children); *it; ++it ) + fromStream( stream, *it ); + } + else { + Q_ASSERT( count == 0 ); + } + + // Now stream in properties + for ( PropertyMapIt mapIt = _map.begin(); mapIt != _map.end(); mapIt++ ) { + QString tp = mapIt.key(); + PropertyList list = mapIt.data(); + if ( to->inherits( tp.latin1() ) ) { + for ( PropertyListIt it = list.begin(); it != list.end(); ++it ) { + QVariant value; + stream >> value; + to->setProperty((*it).latin1(), value); + } + } + } +} + +KWidgetStreamer::KWidgetStreamer () +{ + QStringList l; + + // QCheckBox + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("checked") << QString::fromLatin1("tristate"); + _map.insert(QString::fromLatin1("QCheckBox"), l); + + // QComboBox + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("editable") << QString::fromLatin1("currentItem") + << QString::fromLatin1("maxCount") << QString::fromLatin1("insertionPolicy") + << QString::fromLatin1("autoCompletion"); + _map.insert(QString::fromLatin1("QComboBox"), l); + + // QDial + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("tracking") << QString::fromLatin1("wrapping") + << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QDial"), l); + + // QLCDNumber + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("numDigits") << QString::fromLatin1("mode") + << QString::fromLatin1("segmentStyle") << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QLCDNumber"), l); + + // QLineEdit + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("text") << QString::fromLatin1("maxLength") + << QString::fromLatin1("echoMode") << QString::fromLatin1("alignment"); + _map.insert(QString::fromLatin1("QLineEdit"), l); + + // QMultiLineEdit + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("text") + << QString::fromLatin1("alignment"); + _map.insert(QString::fromLatin1("QTextEdit"), l); + + // QRadioButton + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("checked"); + _map.insert(QString::fromLatin1("QRadioButton"), l); + + // QSlider + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QSlider"), l); + + // QSpinBox + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QSpinBox"), l); +} diff --git a/kregexpeditor/KWidgetStreamer/kwidgetstreamer.h b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.h new file mode 100644 index 0000000..9534a92 --- /dev/null +++ b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kwidgetstreamer +#define __kwidgetstreamer +#include <qmap.h> +#include <qptrlist.h> +#include <qstringlist.h> +#include <qobject.h> + +/** + This class defines methods for streaming widget data. + + For each widget type rules are defined telling which attributes should be + streamed. If you need to stream other attributes or to avoid streaming + certain attributes, then this may be obtained by editing the property + map, which is obtained by calling @ref propertyMap. For further control + inherit from this class and override @ref toStream and @ref fromStream. + + The following example shows how you can avoid streaming + <tt>numDigits</tt> for a QLCDNumber. The same approach applies if you + want to add extra properties to be streamed. + <pre> + KWidgetStreamer streamer; + KWidgetStreamer::PropertyMap& map = streamer.propertyMap(); + KWidgetStreamer::PropertyList& list = *map.find("QLCDNumber"); + list.remove("numDigits"); + </pre> +**/ +class KWidgetStreamer +{ + +public: + typedef QStringList PropertyList; + typedef QMap< QString, PropertyList > PropertyMap; + typedef QMap< QString, PropertyList >::ConstIterator PropertyMapIt; + typedef QStringList::Iterator PropertyListIt; + + KWidgetStreamer(); + virtual ~KWidgetStreamer() {} + + virtual void toStream(const QObject* from, QDataStream& stream ); + virtual void fromStream(QDataStream& stream, QObject* to); + + PropertyMap& propertyMap() { return _map; } + + +protected: + void propertyToStream( const QObject* from, QDataStream& stream ); + void propertyFromStream( QDataStream& stream, QObject* to ); + +private: + PropertyMap _map; + +}; + + + +#endif /* __kwidgetstreamer */ + diff --git a/kregexpeditor/Makefile.am b/kregexpeditor/Makefile.am new file mode 100644 index 0000000..6f8a4e4 --- /dev/null +++ b/kregexpeditor/Makefile.am @@ -0,0 +1,65 @@ +SUBDIRS = KWidgetStreamer KMultiFormListBox picts predefined + +KDE_ICON=AUTO + +AM_CPPFLAGS = -DQT_NO_CAST_ASCII -I$(srcdir)/KWidgetStreamer -I$(srcdir)/KMultiFormListBox $(all_includes) + +# (useless) +noinst_HEADERS = \ + kregexpeditorgui.h editorwindow.h regexpwidget.h drag.h limitedcharlineedit.h regexp.h selectablelineedit.h \ + dragaccepter.h repeatwidget.h concwidget.h textwidget.h characterswidget.h zerowidgets.h multicontainerwidget.h \ + scrollededitorwindow.h compoundwidget.h singlecontainerwidget.h widgetfactory.h dcbutton.h charselector.h \ + lookaheadwidget.h textregexp.h textrangeregexp.h repeatregexp.h lookaheadregexp.h concregexp.h altnregexp.h \ + positionregexp.h dotregexp.h infopage.h kregexpeditorprivate.h compoundregexp.h pair.h triple.h myfontmetrics.h \ + regexpbuttons.h userdefinedregexps.h auxbuttons.h verifier.h verifybuttons.h errormap.h qtregexphighlighter.h \ + regexpconverter.h qtregexpconverter.h emacsregexpconverter.h regexphighlighter.h util.h + +# The library contains all the code that is shared between the module and the app +lib_LTLIBRARIES = libkregexpeditorcommon.la +libkregexpeditorcommon_la_SOURCES = \ + kregexpeditorgui.cpp editorwindow.cpp regexpwidget.cpp drag.cpp concwidget.cpp zerowidgets.cpp dragaccepter.cpp \ + repeatwidget.cpp characterswidget.cpp altnwidget.cpp limitedcharlineedit.cpp textregexp.cpp textrangeregexp.cpp \ + concregexp.cpp altnregexp.cpp positionregexp.cpp dotregexp.cpp repeatregexp.cpp textwidget.cpp \ + selectablelineedit.cpp multicontainerwidget.cpp scrollededitorwindow.cpp compoundwidget.cpp \ + singlecontainerwidget.cpp widgetfactory.cpp dcbutton.cpp gen_qregexplexer.cpp gen_qregexpparser.cc \ + charselector.cpp lookaheadregexp.cpp lookaheadwidget.cpp regexp.cpp infopage.cpp kregexpeditorprivate.cpp \ + compoundregexp.cpp auxbuttons.cpp myfontmetrics.cpp regexpbuttons.cpp userdefinedregexps.cpp verifier.cpp \ + verifybuttons.cpp errormap.cpp qtregexphighlighter.cpp regexpconverter.cpp qtregexpconverter.cpp \ + emacsregexpconverter.cpp regexphighlighter.cpp util.cpp + +libkregexpeditorcommon_la_LDFLAGS = $(all_libraries) -version-info 1:0:0 -no-undefined +libkregexpeditorcommon_la_LIBADD = KMultiFormListBox/libkmultiformlistbox.la \ + KWidgetStreamer/libkwidgetstreamer.la $(LIB_KIO) + +METASOURCES = AUTO + +service_DATA = kregexpeditorgui.desktop +servicedir = $(kde_servicesdir) + +#### The dynamically-loadable module (its interface is defined in kdelibs) +kde_module_LTLIBRARIES = libkregexpeditorgui.la +libkregexpeditorgui_la_SOURCES = kregexpeditorfactory.cpp +libkregexpeditorgui_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +libkregexpeditorgui_la_LIBADD = libkregexpeditorcommon.la + +#### Binary + +bin_PROGRAMS = kregexpeditor +kregexpeditor_SOURCES = main.cpp +kregexpeditor_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kregexpeditor_LDADD = libkregexpeditorcommon.la $(LIB_KIO) +kregexpeditor_INCLUDES = $(all_includes) + +xdg_apps_DATA = kregexpeditor.desktop + + +##### Build rules for the parser + +.PHONY: parser +parser: + cd $(srcdir) && flex -Pqregexp -ogen_qregexplexer.cpp qregexpparser.l + cd $(srcdir) && bison -d -p qregexp -o gen_qregexpparser.cc qregexpparser.y + +messages: + perl extractrc-from-regexp `find . -name "*.regexp"` > predefined-regexps.cpp + $(XGETTEXT) *.cpp *.h */*.cpp */*.h -o $(podir)/kregexpeditor.pot diff --git a/kregexpeditor/TODO b/kregexpeditor/TODO new file mode 100644 index 0000000..d8c492b --- /dev/null +++ b/kregexpeditor/TODO @@ -0,0 +1,49 @@ +TODO: +----- + +When the user drops something on the regular expression area that is of +mime type text/plain, then ask the user whether he want it parsed as a +regular expression or whether he wants it inserted as plain text (that is the text escaped) + +Later wishes: +------------- +- Make the KMultiFormListBox widget support that a line can show several entries. + Use this feature to show two CharSelectors on one line for selecting a single char + in the CharacterWidget. +- Cleanup in the use of repaint(). Several of the repaint() can be update() instead. +- add a checker widget, which can show what the regexp matches from a user defined text. +- add the posibility to travers the widget using the keyboard. +- Highlight the dragaccepter on dragEnter + +Back references +--------------- +- when deleting a compound widget, which has a backreference, what should be done with the + back reference? +- cut/past should preserve back reference id, while cut/copy should create + a new one. +- create interface for extracting information about back references. + +- support back references in the regexp: "(abc|def)\1" + +Modules to go through to search for places to use KRegExpEditor +--------------------------------------------------------------- +KodeKnight +kdeadmin +kdebase +kdeedu +kdegames +kdegraphics +kdeinstaller +kdelibs +kdemultimedia +kdenetwork +kdenonbeta +kdepim +kdesdk +kdetoys +kfte +kmusic +koffice +kpfa +ksite +quanta diff --git a/kregexpeditor/altnregexp.cpp b/kregexpeditor/altnregexp.cpp new file mode 100644 index 0000000..adebf1b --- /dev/null +++ b/kregexpeditor/altnregexp.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "altnregexp.h" +#include "widgetfactory.h" + +AltnRegExp::AltnRegExp( bool selected ) :RegExp( selected ) +{ + // Nothing to do +} + +void AltnRegExp::addRegExp( RegExp *elm ) +{ + list.append( elm ); + addChild( elm ); +} + +RegExpList AltnRegExp::children() const +{ + return list; +} + +bool AltnRegExp::check( ErrorMap& map, bool first, bool last ) +{ + bool possibleEmpty = false; + for ( RegExpListIt it(list); *it; ++it ) { + possibleEmpty = (*it)->check( map, first, last ) || possibleEmpty; + } + return possibleEmpty; +} + +QDomNode AltnRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit( "Alternatives" ) ); + for ( RegExpListIt it(list); *it; ++it ) { + top.appendChild( (*it)->toXml( doc ) ); + } + return top; +} + +bool AltnRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Alternatives" ) ); + + for ( QDomNode child = top.firstChild(); !child.isNull(); child = child.nextSibling() ) { + if ( ! child.isElement() ) + continue; // User might have added a comment. + + RegExp* regexp = WidgetFactory::createRegExp( child.toElement(), version ); + if ( regexp == 0 ) + return false; + addRegExp( regexp ); + } + return true; + +} + +bool AltnRegExp::operator==( const RegExp& other ) const +{ + // TODO: merge with ConcRegExp::operator== + + if ( other.type() != type() ) + return false; + + const AltnRegExp& theOther = dynamic_cast<const AltnRegExp&>( other ); + + if ( list.count() != theOther.list.count() ) + return false; + + RegExpListIt it1( list ); + RegExpListIt it2( theOther.list ); + + for ( ; *it1 && *it2 ; ) { + if ( ! (**it1 == **it2) ) + return false; + ++it1; + ++it2; + } + return true; +} + +void AltnRegExp::replacePart( CompoundRegExp* replacement ) +{ + for ( RegExpListIt it( list ); *it; ++it ) { + (*it)->replacePart( replacement ); + } +} + diff --git a/kregexpeditor/altnregexp.h b/kregexpeditor/altnregexp.h new file mode 100644 index 0000000..d5d9d1e --- /dev/null +++ b/kregexpeditor/altnregexp.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef ALTNREGEXP_H +#define ALTNREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `alternative' regular expression + @internal +*/ +class AltnRegExp :public RegExp +{ +public: + AltnRegExp( bool selected ); + + void addRegExp( RegExp * ); + RegExpList children() const; + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 1;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return ALTN;} + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ); + +private: + RegExpList list; +}; + +#endif // ALTNREGEXP_H diff --git a/kregexpeditor/altnwidget.cpp b/kregexpeditor/altnwidget.cpp new file mode 100644 index 0000000..22937ac --- /dev/null +++ b/kregexpeditor/altnwidget.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kmessagebox.h> +#endif + +#include "altnwidget.h" +#include "dragaccepter.h" +#include "concwidget.h" +#include "altnregexp.h" +#include <qpainter.h> + +AltnWidget::AltnWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + :MultiContainerWidget(editorWindow, parent, name == 0 ? "AltnWidget" : name) +{ + DragAccepter *accepter = new DragAccepter(editorWindow, this); + accepter->resize(0,0); // See note (1) in Comments + _children.append(accepter); + _text = i18n("Alternatives"); +} + +AltnWidget::AltnWidget( AltnRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name) + :MultiContainerWidget( editorWindow, parent, name ) +{ + DragAccepter *accepter = new DragAccepter(editorWindow, this); + accepter->resize(0,0); // See note (1) in Comments + _children.append(accepter); + _text = i18n("Alternatives"); + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + RegExpWidget* child = WidgetFactory::createWidget( *it, editorWindow, this ); + ConcWidget* conc; + if ( ! (conc = dynamic_cast<ConcWidget*>( child ) ) ) { + conc = new ConcWidget( editorWindow, child, parent ); + } + append( conc ); + } + updateDrawLineInfo(); +} + + +void AltnWidget::addNewChild(DragAccepter *accepter, RegExpWidget *child) +{ + ConcWidget *conc = new ConcWidget(_editorWindow, child,this); + MultiContainerWidget::addNewChild( accepter, conc ); + updateDrawLineInfo(); + repaint(); +} + +void AltnWidget::setConcChild(ConcWidget *child) +{ + addNewConcChild( dynamic_cast<DragAccepter*>(_children.at(0)), child ); +} + +void AltnWidget::addNewConcChild(DragAccepter *accepter, ConcWidget *child) +{ + child->reparent(this, QPoint(0,0), false); + MultiContainerWidget::addNewChild( accepter, child ); + updateDrawLineInfo(); +} + + +QSize AltnWidget::sizeHint() const +{ + QPtrListIterator<RegExpWidget> it(_children); + // Skip the first child, as we only need half of the size of the first and the + // last drag accepter. Does, however, not apply when there only is onw child. + if ( _children.count() != 1 ) + ++it; + + _childrenWidth = 0; + _childrenHeight = 0; + + for ( ; *it ; ++it) { + QSize thisChildSize = (*it)->sizeHint(); + _childrenWidth = QMAX(_childrenWidth, thisChildSize.width()); + _childrenHeight += thisChildSize.height(); + } + + // Now add the size of the header + QFontMetrics metrics = fontMetrics(); + _textSize = metrics.size(0,_text); + + int headerWidth = _textSize.width() + 2 * bdSize + 2; + + _childrenWidth = QMAX(_childrenWidth, headerWidth); + + return QSize(_childrenWidth + 2*pw, _childrenHeight + _textSize.height() + 1*pw ); +} + +void AltnWidget::paintEvent( QPaintEvent *e) +{ + Q_ASSERT( dynamic_cast<DragAccepter*>(_children.at(0)) ); + // if this fails, then I should check the location of the show() + Q_ASSERT( _children.count() == 1 || + ( _children.count() >=3 && + dynamic_cast<DragAccepter*>(_children.at(_children.count()-1)) ) ); + + int offset = 0; + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize ); + + //-------------------------------------- First draw the border and text + int startY = _textSize.height()/2; + + painter.drawLine(0, startY, bdSize, startY); + int xOffset = bdSize +1; + + painter.drawText(xOffset,0,_textSize.width(), _textSize.height(),0,_text); + xOffset += _textSize.width() +1; + painter.drawLine(xOffset,startY,mySize.width(), startY); + painter.drawLine(0,startY,0,mySize.height()); + painter.drawLine(mySize.width()-pw, startY, mySize.width()-pw, mySize.height()); + painter.drawLine(0,mySize.height()-pw, mySize.width()-pw, mySize.height()-pw); + + //---- Run through all the children and place them at the correct location. + offset = _textSize.height(); + xOffset = pw; + + for (unsigned int i = 0; i < _children.count(); i++ ) { + + RegExpWidget* child = _children.at(i); + + QSize childSize = child->sizeHint(); + QSize curChildSize = child->size(); + + //-------------------------------------- place the child + int x = xOffset; + int y = offset; + int h = childSize.height(); + if ( ( _children.count() != 1 ) && ( i == 0 || i == _children.count() -1 ) ) { + // first and last DragAccepter should only be half size. + h /= 2; + } + + int w = _childrenWidth; + child->setGeometry( x, y, w, h ); + if ( w != curChildSize.width() || h != curChildSize.height() ) { + // I resized the child, so give it a chance to relect thus. + child->update(); + } + + offset += h; + } + MultiContainerWidget::paintEvent( e ); +} + +RegExp* AltnWidget::regExp() const +{ + AltnRegExp *regexp = new AltnRegExp( isSelected() ); + + QPtrListIterator<RegExpWidget> it(_children); + ++it; // start with the second element + for ( ; *it; it+=2 ) { + regexp->addRegExp( (*it)->regExp() ); + } + + return regexp; +} + +void AltnWidget::applyRegExpToSelection( RegExpType type ) +{ + for ( unsigned int i=1; i < _children.count(); i += 2 ) { + RegExpWidget* child = _children.at( i ); + if ( child->hasSelection() ) { + child->applyRegExpToSelection( type ); + } + } +} + + +RegExp* AltnWidget::selection() const +{ + if ( isSelected() ) + return regExp(); + else { + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Skip past DragAccepter + for ( ; *it; it+=2 ) { + if ( (*it)->hasSelection() ) { + return (*it)->selection(); + } + } + } + qFatal("Selection not found"); + return 0; // compiler shut up. +} + +bool AltnWidget::validateSelection() const +{ + if ( _isSelected ) { + return true; + } + + bool foundASelection = false; + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Skip past DragAccepter + for ( ; *it; it+=2 ) { + if ( (*it)->hasSelection() ) { + if ( foundASelection ) { + KMessageBox::information( const_cast<AltnWidget*>(this), + i18n( "Selecting several alternatives is " + "currently not supported." ), + i18n( "Selection Invalid" ) ); + _editorWindow->clearSelection( true ); + return false; + } + else { + foundASelection = true; + } + } + } + return true; +} + +void AltnWidget::updateDrawLineInfo() +{ + for ( unsigned int i=0; i < _children.count(); i+=2 ) { + bool line = ( i != 0 && i!= _children.count()-1 ); + DragAccepter *accepter = dynamic_cast<DragAccepter*>(_children.at(i)); + if (accepter) + accepter->setDrawLine( line ); + } +} + +void AltnWidget::deleteSelection() +{ + MultiContainerWidget::deleteSelection(); + updateDrawLineInfo(); +} + diff --git a/kregexpeditor/altnwidget.h b/kregexpeditor/altnwidget.h new file mode 100644 index 0000000..9a4f26b --- /dev/null +++ b/kregexpeditor/altnwidget.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef altnwidget +#define altnwidget + +#include "multicontainerwidget.h" +class AltnRegExp; + +/** + RegExp widget for alternatives. + + @internal +*/ +class AltnWidget :public MultiContainerWidget +{ +public: + AltnWidget( RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + AltnWidget( AltnRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual void applyRegExpToSelection( RegExpType type ); + virtual RegExpType type() const { return ALTN; } + virtual RegExp* selection() const; + virtual bool validateSelection() const; + virtual void setConcChild(ConcWidget *child); + virtual void addNewConcChild(DragAccepter *accepter, ConcWidget *child); + virtual void deleteSelection(); + +protected: + virtual void paintEvent( QPaintEvent* e ); + +private: + /** + This functions runs through all the dragaccepters and calls @ref + DragAccepter::setDrawLine. + */ + void updateDrawLineInfo(); + + QString _text; + mutable QSize _textSize; + + mutable int _maxSelectedWidth; + mutable int _childrenWidth; + mutable int _childrenHeight; +}; + +#endif // altnwidget diff --git a/kregexpeditor/auxbuttons.cpp b/kregexpeditor/auxbuttons.cpp new file mode 100644 index 0000000..ea28953 --- /dev/null +++ b/kregexpeditor/auxbuttons.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include "auxbuttons.moc" + #include <kiconloader.h> + #include <klocale.h> +#endif + +#include "auxbuttons.h" +#include <qlayout.h> +#include <qwhatsthis.h> +#include <qtooltip.h> +#include <qtoolbutton.h> +#include "util.h" + +AuxButtons::AuxButtons( QWidget* parent, const char* name = 0) + :QDockWindow( QDockWindow::InDock, parent, name) +{ + QBoxLayout* layout = boxLayout(); + + _undo = new QToolButton( this ); + _undo->setIconSet( Util::getSystemIconSet(QString::fromLatin1("undo") ) ); + layout->addWidget( _undo ); + connect( _undo, SIGNAL(clicked()), this, SIGNAL(undo()) ); + QToolTip::add( _undo, i18n( "Undo" ) ); + + _redo = new QToolButton( this ); + _redo->setIconSet( Util::getSystemIconSet(QString::fromLatin1("redo") ) ); + layout->addWidget( _redo ); + connect( _redo, SIGNAL(clicked()), this, SIGNAL(redo()) ); + QToolTip::add( _redo, i18n( "Redo" ) ); + + _cut = new QToolButton( this ); + _cut->setIconSet( Util::getSystemIconSet(QString::fromLatin1("editcut") ) ); + layout->addWidget( _cut ); + connect( _cut, SIGNAL(clicked()), this, SIGNAL(cut()) ); + QToolTip::add( _cut, i18n( "Cut" ) ); + + _copy = new QToolButton( this ); + _copy->setIconSet( Util::getSystemIconSet(QString::fromLatin1("editcopy") ) ); + layout->addWidget( _copy ); + connect( _copy, SIGNAL(clicked()), this, SIGNAL(copy()) ); + QToolTip::add( _copy, i18n( "Copy" ) ); + + _paste = new QToolButton( this ); + _paste->setIconSet( Util::getSystemIconSet(QString::fromLatin1("editpaste")) ); + layout->addWidget( _paste ); + connect( _paste, SIGNAL(clicked()), this, SIGNAL(paste()) ); + QToolTip::add( _paste, i18n( "Paste" ) ); + + _save = new QToolButton( this ); + _save->setIconSet( Util::getSystemIconSet(QString::fromLatin1("filesave")) ); + layout->addWidget( _save ); + connect( _save, SIGNAL(clicked()), this, SIGNAL(save()) ); + QToolTip::add( _save, i18n( "Save" ) ); + + + QToolButton* button = new QToolButton(this); + button->setPixmap( Util::getSystemIcon( QString::fromLatin1("contexthelp") ) ); + layout->addWidget( button ); + connect(button, SIGNAL(clicked()), this, SLOT(slotEnterWhatsThis())); + + _undo->setEnabled( false ); + _redo->setEnabled( false ); + +} + +void AuxButtons::slotEnterWhatsThis() +{ + QWhatsThis::enterWhatsThisMode (); +} + +void AuxButtons::slotCanUndo( bool b ) +{ + _undo->setEnabled( b ); +} + +void AuxButtons::slotCanRedo( bool b ) +{ + _redo->setEnabled( b ); +} + +void AuxButtons::slotCanCut( bool b ) +{ + _cut->setEnabled( b ); +} + +void AuxButtons::slotCanCopy( bool b ) +{ + _copy->setEnabled( b ); +} + +void AuxButtons::slotCanPaste( bool b ) +{ + _paste->setEnabled( b ); +} + +void AuxButtons::slotCanSave( bool b ) +{ + _save->setEnabled( b ); +} + diff --git a/kregexpeditor/auxbuttons.h b/kregexpeditor/auxbuttons.h new file mode 100644 index 0000000..08c33ec --- /dev/null +++ b/kregexpeditor/auxbuttons.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef AUXBUTTONS_H +#define AUXBUTTONS_H + +#include <qdockwindow.h> +class QComboBox; +class QLabel; +class QToolButton; + +class AuxButtons :public QDockWindow +{ + Q_OBJECT + +public: + AuxButtons( QWidget* parent, const char* name ); + +signals: + void undo(); + void redo(); + void cut(); + void copy(); + void paste(); + void save(); + +public slots: + void slotEnterWhatsThis(); + void slotCanUndo( bool ); + void slotCanRedo( bool ); + void slotCanCut( bool ); + void slotCanCopy( bool ); + void slotCanPaste( bool ); + void slotCanSave( bool ); + +private: + QToolButton* _undo; + QToolButton* _redo; + QToolButton* _cut; + QToolButton* _copy; + QToolButton* _paste; + QToolButton* _save; +}; + + +#endif // AUXBUTTONS_H diff --git a/kregexpeditor/characterswidget.cpp b/kregexpeditor/characterswidget.cpp new file mode 100644 index 0000000..b219ed6 --- /dev/null +++ b/kregexpeditor/characterswidget.cpp @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <kdialogbase.h> + #include "characterswidget.moc" +#endif + +#include "characterswidget.h" +#include "textrangeregexp.h" +#include "regexp.h" +#include "charselector.h" +#include "myfontmetrics.h" +#include "regexpconverter.h" + +#include <qpainter.h> +#include <qgrid.h> +#include <iostream> +#include <qhgroupbox.h> +#include <qcursor.h> +#include <qcheckbox.h> + +CharacterEdits* CharactersWidget::_configWindow = 0; + +CharactersWidget::CharactersWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : RegExpWidget(editorWindow, parent, name) +{ + _regexp = new TextRangeRegExp( false /* not used */); +} + +CharactersWidget::CharactersWidget( TextRangeRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + : RegExpWidget( editorWindow, parent, name ) +{ + _regexp = dynamic_cast<TextRangeRegExp*>( regexp->clone() ); + Q_ASSERT( _regexp ); +} + +CharactersWidget::~CharactersWidget() +{ + delete _regexp; +} + + +QSize CharactersWidget::sizeHint() const +{ + QFontMetrics metrics = fontMetrics(); + _textSize = HackCalculateFontSize(metrics, title()); + // _textSize = metrics.size(0, title()); + + QSize headerSize = QSize(_textSize.width() + 4 * bdSize, + _textSize.height()); + + _contentSize = HackCalculateFontSize(metrics,text()); + // _contentSize = metrics.size(0, text()); + + return QSize(QMAX(headerSize.width(), bdSize + _contentSize.width() + bdSize+ 2*pw), + headerSize.height() + bdSize + _contentSize.height() + bdSize + 2*pw); +} + +void CharactersWidget::paintEvent(QPaintEvent *e) +{ + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize ); + + int center = _textSize.height()/2; + int offset = 0; + + // draw the horizontal line and the label + painter.drawLine(pw,center, bdSize,center); + offset += pw + 2*bdSize; + + painter.drawText(offset, 0, _textSize.width(), _textSize.height(), 0, title()); + offset += _textSize.width() + bdSize; + + painter.drawLine(offset, center, mySize.width(), center); + + // Draw the rest of the lines + int y = mySize.width() - pw; + int x = mySize.height() -pw; + painter.drawLine(0,center,0,mySize.height()); + painter.drawLine(y,center,y,mySize.height()); + painter.drawLine(0,x,y,x); + + // Draw the text + painter.drawText(bdSize, bdSize+_textSize.height(), _contentSize.width(), + _contentSize.height(), 0, text()); + + RegExpWidget::paintEvent(e); +} + +RegExp* CharactersWidget::regExp() const +{ + RegExp* r = _regexp->clone(); + r->setSelected( isSelected() ); + return r; +} + +QString CharactersWidget::text() const +{ + QString res = QString::fromLatin1(""); + + if (_regexp->wordChar()) + res += i18n("- A word character\n"); + + if (_regexp->nonWordChar()) + res += i18n("- A non-word character\n"); + + if (_regexp->digit()) + res += i18n("- A digit character\n"); + + if (_regexp->nonDigit()) + res += i18n("- A non-digit character\n"); + + if ( _regexp->space() ) + res += i18n("- A space character\n"); + + if ( _regexp->nonSpace() ) + res += i18n("- A non-space character\n"); + + // Single characters + QStringList chars = _regexp->chars(); + if ( !chars.isEmpty() ) { + QString str = chars.join( QString::fromLocal8Bit(", ") ); + res += QString::fromLocal8Bit("- ") + str + QString::fromLocal8Bit("\n"); + } + + // Ranges characters + QPtrList<StringPair> range = _regexp->range(); + for ( QPtrListIterator<StringPair> it( range ); *it; ++it ) { + StringPair* elm = static_cast<StringPair*>(*it); + if (elm) { + QString fromText = elm->first(); + QString toText = elm->second(); + + res += QString::fromLocal8Bit("- ") + i18n("from ") + fromText + i18n(" to ") + toText + QString::fromLocal8Bit("\n"); + } + } + return res.left(res.length()-1); +} + + +QString CharactersWidget::title() const +{ + if (_regexp->negate()) + return i18n("Any Character Except"); + else + return i18n("One of Following Characters"); +} + + +RegExpWidget* CharactersWidget::findWidgetToEdit( QPoint globalPos ) +{ + if ( QRect(mapToGlobal(QPoint(0,0)), size()).contains( globalPos ) ) + return this; + else + return 0; +} + +int CharactersWidget::edit() +{ + if ( _configWindow == 0 ) { + QApplication::setOverrideCursor( WaitCursor ); + // No parent here, as this window should continue to exists. + _configWindow = new CharacterEdits( 0, "CharactersWidget::_configWindow" ); + QApplication::restoreOverrideCursor(); + } + + _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width()/2, + _configWindow->sizeHint().height()/2)); + int ret = _configWindow->exec(_regexp ); + if ( ret == QDialog::Accepted ) { + _editorWindow->updateContent( 0 ); + update(); + } + return ret; +} + +void CharacterEdits::addCharacter( QString txt ) +{ + KMultiFormListBoxEntryList list = _single->elements(); + for ( QPtrListIterator<KMultiFormListBoxEntry> it(list); *it; ++it ) { + SingleEntry* entry = dynamic_cast<SingleEntry*>( *it ); + if ( entry && entry->isEmpty() ) { + entry->setText( txt ); + return; + } + } + + SingleEntry* entry = new SingleEntry( _single ); + entry->setText( txt ); + _single->append( entry ); +} + +void CharacterEdits::addRange( QString from, QString to ) +{ + KMultiFormListBoxEntryList list = _range->elements(); + for ( QPtrListIterator<KMultiFormListBoxEntry> it(list); *it; ++it ) { + RangeEntry* entry = dynamic_cast<RangeEntry*>( *it ); + if ( entry && entry->isEmpty() ) { + entry->setFrom( from ); + entry->setTo( to ); + return; + } + } + + RangeEntry* entry = new RangeEntry( _range ); + entry->setFrom( from ); + entry->setTo( to ); + _range->append( entry ); +} + +int CharacterEdits::exec( TextRangeRegExp* regexp ) +{ + _regexp = regexp; + negate->setChecked( regexp->negate() ); + digit->setChecked( regexp->digit() ); + _nonDigit->setChecked( regexp->nonDigit() ); + space->setChecked( regexp->space() ); + _nonSpace->setChecked( regexp->nonSpace() ); + wordChar->setChecked( regexp->wordChar() ); + _nonWordChar->setChecked( regexp->nonWordChar() ); + + bool enabled = (RegExpConverter::current()->features() & RegExpConverter::CharacterRangeNonItems); + _nonWordChar->setEnabled( enabled ); + _nonDigit->setEnabled( enabled ); + _nonSpace->setEnabled( enabled ); + + // Characters + + KMultiFormListBoxEntryList list1 = _single->elements(); + for ( QPtrListIterator<KMultiFormListBoxEntry> it(list1); *it; ++it ) { + SingleEntry* entry = dynamic_cast<SingleEntry*>( *it ); + if (entry) + entry->setText( QString::fromLocal8Bit("") ); + } + QStringList list2 = regexp->chars(); + for ( QStringList::Iterator it2( list2.begin() ); ! (*it2).isNull(); ++it2 ) { + addCharacter( *it2 ); + } + + // Ranges + KMultiFormListBoxEntryList list3 = _range->elements(); + for ( QPtrListIterator<KMultiFormListBoxEntry> it3(list3); *it3; ++it3 ) { + RangeEntry* entry = dynamic_cast<RangeEntry*>( *it3 ); + if (entry) { + entry->setFrom( QString::fromLocal8Bit("") ); + entry->setTo( QString::fromLocal8Bit("") ); + } + } + + QPtrList<StringPair> ranges = regexp->range(); + for ( QPtrListIterator<StringPair> it4(ranges); *it4; ++it4 ) { + QString from = (*it4)->first(); + QString to = (*it4)->second(); + addRange(from,to); + } + + int res = KDialogBase::exec(); + _regexp = 0; + return res; +} + + +CharacterEdits::CharacterEdits( QWidget *parent, const char *name) + : KDialogBase( parent, name == 0 ? "CharacterEdits" : name, true, + i18n("Specify Characters"), + KDialogBase::Ok | KDialogBase::Cancel) +{ + QWidget* top = new QWidget( this ); + QVBoxLayout *topLayout = new QVBoxLayout(top, 6); + setMainWidget( top ); + + negate = new QCheckBox(i18n("Do not match the characters specified here"), + top); + topLayout->addWidget( negate ); + + + // The predefined box + QHGroupBox* predefined = new QHGroupBox(i18n("Predefined Character Ranges"),top); + topLayout->addWidget(predefined); + QGrid* grid = new QGrid(3, predefined ); + + wordChar = new QCheckBox(i18n("A word character"),grid); + digit = new QCheckBox(i18n("A digit character"),grid); + space = new QCheckBox(i18n("A space character"), grid); + + _nonWordChar = new QCheckBox(i18n("A non-word character"),grid); + _nonDigit = new QCheckBox(i18n("A non-digit character"),grid); + _nonSpace = new QCheckBox(i18n("A non-space character"), grid); + + // Single characters + QVGroupBox* singleBox = new QVGroupBox(i18n("Single Characters"), top ); + topLayout->addWidget( singleBox ); + _single = new KMultiFormListBox(new SingleFactory(), KMultiFormListBox::MultiVisible, + singleBox); + _single->addElement(); _single->addElement(); _single->addElement(); + + QWidget* moreW = new QWidget( singleBox ); + QHBoxLayout* moreLay = new QHBoxLayout( moreW ); + QPushButton* more = new QPushButton( i18n("More Entries"), moreW ); + moreLay->addWidget( more ); + moreLay->addStretch( 1 ); + + connect(more,SIGNAL(clicked()), _single, SLOT(addElement())); + + // Ranges + QVGroupBox* rangeBox = new QVGroupBox(i18n("Character Ranges"), top ); + topLayout->addWidget( rangeBox ); + + _range = new KMultiFormListBox(new RangeFactory(), KMultiFormListBox::MultiVisible, + rangeBox); + _range->addElement(); _range->addElement(); _range->addElement(); + + moreW = new QWidget( rangeBox ); + moreLay = new QHBoxLayout( moreW ); + more = new QPushButton( i18n("More Entries"), moreW ); + moreLay->addWidget( more ); + moreLay->addStretch( 1 ); + connect(more,SIGNAL(clicked()), _range, SLOT(addElement())); + // Buttons + connect(this, SIGNAL(okClicked()), this, SLOT(slotOK())); +} + +void CharacterEdits::slotOK() +{ + _regexp->setNegate( negate->isChecked() ); + + _regexp->setWordChar( wordChar->isChecked() ); + _regexp->setNonWordChar( _nonWordChar->isChecked() ); + + _regexp->setDigit( digit->isChecked() ); + _regexp->setNonDigit( _nonDigit->isChecked() ); + + _regexp->setSpace( space->isChecked() ); + _regexp->setNonSpace( _nonSpace->isChecked() ); + + // single characters + _regexp->clearChars(); + KMultiFormListBoxEntryList list = _single->elements(); + for ( QPtrListIterator<KMultiFormListBoxEntry> it( list ); *it; ++it ) { + SingleEntry* entry = dynamic_cast<SingleEntry*>(*it); + if ( entry && !entry->isEmpty() ) { + _regexp->addCharacter( entry->text() ); + } + } + + // Ranges + _regexp->clearRange(); + list = _range->elements(); + for ( QPtrListIterator<KMultiFormListBoxEntry> it2( list ); *it2; ++it2 ) { + RangeEntry* entry = dynamic_cast<RangeEntry*>(*it2); + if ( entry && !entry->isEmpty() ) { + _regexp->addRange( entry->fromText(), entry->toText() ); + } + } +} + + +SingleEntry::SingleEntry(QWidget* parent, const char* name ) + :KMultiFormListBoxEntry( parent, name ) +{ + QHBoxLayout* layout = new QHBoxLayout( this, 3, 6 ); + _selector = new CharSelector( this ); + layout->addWidget( _selector ); + layout->addStretch(1); +} + +QString SingleEntry::text() const +{ + return _selector->text(); +} + +void SingleEntry::setText( QString text ) +{ + _selector->setText( text ); +} + +bool SingleEntry::isEmpty() const +{ + return _selector->isEmpty(); +} + + +RangeEntry::RangeEntry(QWidget* parent, const char* name ) + :KMultiFormListBoxEntry( parent, name ) +{ + QHBoxLayout* layout = new QHBoxLayout( this, 3, 6 ); + + QLabel* label = new QLabel(i18n("From:"), this ); + _from = new CharSelector( this ); + layout->addWidget( label ); + layout->addWidget( _from ); + + layout->addStretch(1); + + label = new QLabel(i18n("end of range","To:"), this ); + _to = new CharSelector( this ); + layout->addWidget( label ); + layout->addWidget( _to ); +} + +QString RangeEntry::fromText() const +{ + return _from->text(); +} + +QString RangeEntry::toText() const +{ + return _to->text(); +} + +void RangeEntry::setFrom( QString text ) +{ + _from->setText( text ); +} + +void RangeEntry::setTo( QString text ) +{ + _to->setText( text ); +} + +bool RangeEntry::isEmpty() const +{ + return _from->isEmpty() || _to->isEmpty(); +} + diff --git a/kregexpeditor/characterswidget.h b/kregexpeditor/characterswidget.h new file mode 100644 index 0000000..9df89b3 --- /dev/null +++ b/kregexpeditor/characterswidget.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef characterswidget +#define characterswidget + +#ifdef QT_ONLY +#include "compat.h" +#else +#include <kdialogbase.h> +#endif + +#include <kmultiformlistbox.h> +#include "regexpwidget.h" +#include <qvgroupbox.h> + +class KDialogBase; +class CharacterEdits; +class TextRangeRegExp; +class CharSelector; +class QCheckBox; + +/** + RegExp widget for charcter ranges. + @internal +*/ +class CharactersWidget :public RegExpWidget +{ +public: + CharactersWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + CharactersWidget( TextRangeRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0 ); + ~CharactersWidget(); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return CHARSET; } + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + virtual int edit(); + +protected: + virtual void paintEvent(QPaintEvent *event); + QString text() const; + QString title() const; + +private: + TextRangeRegExp *_regexp; + static CharacterEdits *_configWindow; + + mutable QSize _textSize; + mutable QSize _contentSize; +}; + + +/** + @internal +*/ +class SingleEntry :public KMultiFormListBoxEntry +{ +public: + SingleEntry(QWidget* parent, const char* name = 0 ); + QString text() const; + void setText( QString text ); + bool isEmpty() const; + +private: + CharSelector* _selector; +}; + +/** + @internal +*/ +class RangeEntry :public KMultiFormListBoxEntry +{ +public: + RangeEntry(QWidget* parent, const char* name = 0 ); + QString fromText() const; + QString toText() const; + void setFrom( QString text ); + void setTo( QString text ); + bool isEmpty() const; +private: + CharSelector *_from, *_to; +}; + +/** + @internal +*/ +class SingleFactory :public KMultiFormListBoxFactory +{ +public: + KMultiFormListBoxEntry *create(QWidget *parent) { return new SingleEntry( parent ); } + QWidget *separator( QWidget* ) { return 0; } +}; + +/** + @internal +*/ +class RangeFactory :public KMultiFormListBoxFactory +{ +public: + KMultiFormListBoxEntry *create(QWidget *parent) { return new RangeEntry( parent ); } + QWidget *separator( QWidget* ) { return 0; } +}; + +/** + @internal +*/ +class CharacterEdits : public KDialogBase +{ + Q_OBJECT +public: + CharacterEdits(QWidget *parent = 0, const char *name = 0); + +public slots: + int exec( TextRangeRegExp* regexp ); + +protected slots: + void slotOK(); + +private: + QCheckBox *negate, *wordChar, *_nonWordChar, *digit, *_nonDigit, *space, *_nonSpace; + KMultiFormListBox *_single, *_range; + + void addCharacter( QString txt ); + void addRange( QString from, QString to ); + TextRangeRegExp* _regexp; +}; + +#endif // characterswidget diff --git a/kregexpeditor/charselector.cpp b/kregexpeditor/charselector.cpp new file mode 100644 index 0000000..27fd23d --- /dev/null +++ b/kregexpeditor/charselector.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY +#include "compat.h" +#else +#include <klocale.h> +#include "charselector.moc" +#endif + +#include "charselector.h" +#include "limitedcharlineedit.h" +#include "regexpconverter.h" +#include <qlayout.h> +#include <qwidgetstack.h> +#include <qcombobox.h> + +/** + In the class CharSelector, three LimitedCharLineEdit are used. + These widgets are all used in a QWidgetStack. The LimitedCharLineEdit + class is basically a QLineEdit, which is limited to a certain + number of characters. This conflicts with the QWidgetStack, as this + class expects the widgets on the stack to take up all space. + StackContainer fills in this gab. +*/ +class StackContainer :public QWidget +{ +public: + StackContainer( QWidget* child, QWidget* parent ) : QWidget( parent ) + { + QHBoxLayout* layout = new QHBoxLayout( this ); + child->reparent( this, QPoint(0,0), false ); + layout->addWidget( child ); + layout->addStretch( 1 ); + } +}; + +CharSelector::CharSelector( QWidget* parent, const char* name ) + :QWidget( parent, name ), _oldIndex(0) +{ + QStringList items; + QHBoxLayout* layout = new QHBoxLayout( this, 0, 6 ); + + _type = new QComboBox( this, "_type" ); + items << i18n("Normal Character") + << i18n("Unicode Char in Hex.") + << i18n("Unicode Char in Oct.") + << QString::fromLatin1("----") + << i18n("The Bell Character (\\a)") + << i18n("The Form Feed Character (\\f)") + << i18n("The Line Feed Character (\\n)") + << i18n("The Carriage Return Character (\\r)") + << i18n("The Horizontal Tab Character (\\t)") + << i18n("The Vertical Tab Character (\\v)"); + _type->insertStringList( items ); + layout->addWidget( _type ); + + _stack = new QWidgetStack( this, "_stack" ); + layout->addWidget( _stack ); + + _normal = new LimitedCharLineEdit( LimitedCharLineEdit::NORMAL, 0, "_normal" ); + _stack->addWidget( new StackContainer( _normal, _stack ), 0 ); + + _hex = new LimitedCharLineEdit( LimitedCharLineEdit::HEX, _stack, "_hex" ); + _stack->addWidget( new StackContainer( _hex, _stack ), 1 ); + + _oct = new LimitedCharLineEdit( LimitedCharLineEdit::OCT, _stack, "_oct" ); + _stack->addWidget( new StackContainer( _oct, _stack ), 2 ); + + _stack->raiseWidget( 0 ); + + connect( _type, SIGNAL( activated( int ) ), this, SLOT(slotNewItem( int ) ) ); +} + +void CharSelector::slotNewItem( int which ) +{ + _type->setCurrentItem( which ); + if ( which <= 2 ) { + _stack->raiseWidget( which ); + _normal->setEnabled( true ); + _hex->setEnabled( true ); + _oct->setEnabled( true ); + } + else if ( which == 3 ) { + _type->setCurrentItem( _oldIndex ); + slotNewItem(_oldIndex); + return; + } + else { + _normal->setEnabled( false ); + _hex->setEnabled( false ); + _oct->setEnabled( false ); + } + + _oldIndex = which; +} + +void CharSelector::setText( QString text ) +{ + // This is the best I can do about missing character range features, unless all of + // textrangeregexp is to be reworked. The problem is that textrangeregexp only allows to + // get the characters, which would be something like \a, but \a does not work with say Emacs + // style regexps -- ko28 Sep. 2003 10:55 -- Jesper K. Pedersen + bool enabled = ( RegExpConverter::current()->features() & RegExpConverter::ExtRange ); + _type->setEnabled( enabled ); + + if ( text.at(0) == QChar('\\') ) { + if ( text.at(1) == QChar('x') ) { + _hex->setText(text.mid(2)); + slotNewItem( 1 ); + } + else if ( text.at(1) == QChar('0') ) { + _oct->setText(text.mid(2)); + slotNewItem( 2 ); + } + else if ( text.at(1) == QChar('a') ) + slotNewItem(4); + else if ( text.at(1) == QChar('f') ) + slotNewItem(5); + else if ( text.at(1) == QChar('n') ) + slotNewItem(6); + else if ( text.at(1) == QChar('r') ) + slotNewItem(7); + else if ( text.at(1) == QChar('t') ) + slotNewItem(8); + else if ( text.at(1) == QChar('v') ) + slotNewItem(9); + else { + qWarning("Warning %s:%d Unknown escape %s", __FILE__, __LINE__, text.latin1() ); + } + } + else { + slotNewItem(0); + _normal->setText(text); + } +} + +bool CharSelector::isEmpty() const +{ + return ( _type->currentItem() == 0 && _normal->text().isEmpty() ) || + ( _type->currentItem() == 1 && _hex->text().isEmpty() ) || + ( _type->currentItem() == 2 && _oct->text().isEmpty() ); +} + +QString CharSelector::text() const +{ + switch ( _type->currentItem() ) { + case 0: // Normal Character + return _normal->text(); + case 1: // Hex + return QString::fromLocal8Bit("\\x") + _hex->text(); + case 2: // Oct + return QString::fromLocal8Bit("\\0") + _oct->text(); + case 3: // The seperator + break; + case 4: + return QString::fromLatin1("\\a"); + case 5: + return QString::fromLatin1("\\f"); + case 6: + return QString::fromLatin1("\\n"); + case 7: + return QString::fromLatin1("\\r"); + case 8: + return QString::fromLatin1("\\t"); + case 9: + return QString::fromLatin1("\\v"); + } + return QString::null; +} diff --git a/kregexpeditor/charselector.h b/kregexpeditor/charselector.h new file mode 100644 index 0000000..07aa056 --- /dev/null +++ b/kregexpeditor/charselector.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef CHARSELECTOR_H +#define CHARSELECTOR_H + +#include <qwidget.h> + +class QComboBox; +class QWidgetStack; +class LimitedCharLineEdit; + +class CharSelector :public QWidget +{ + Q_OBJECT + +public: + CharSelector( QWidget* parent, const char* name = 0 ); + QString text() const; + void setText( QString text ); + bool isEmpty() const; + +protected: + void fillComboBox(); + +private slots: + void slotNewItem( int which ); + +private: + QComboBox* _type; + QWidgetStack* _stack; + LimitedCharLineEdit* _normal; + LimitedCharLineEdit* _hex; + LimitedCharLineEdit* _oct; + int _oldIndex; +}; + +#endif // CHARSELECTOR_H diff --git a/kregexpeditor/compoundregexp.cpp b/kregexpeditor/compoundregexp.cpp new file mode 100644 index 0000000..2949b48 --- /dev/null +++ b/kregexpeditor/compoundregexp.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> +#endif + +#include "compoundregexp.h" +#include "widgetfactory.h" + +CompoundRegExp::CompoundRegExp( bool selected, const QString& title, const QString& description, bool hidden, + bool allowReplace, RegExp* child) + : RegExp( selected ), _title( title ), _description( description ), _hidden( hidden ), _allowReplace( allowReplace ), _child( child ) +{ + if ( child ) + addChild( child ); +} + +bool CompoundRegExp::check( ErrorMap& map, bool first, bool last ) +{ + return _child->check( map, first, last ); +} + +QDomNode CompoundRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit( "Compound" ) ); + if (_hidden) + top.setAttribute( QString::fromLocal8Bit("hidden"), true ); + if ( _allowReplace ) + top.setAttribute( QString::fromLocal8Bit("allowReplace"), true ); + + QDomElement title = doc->createElement( QString::fromLocal8Bit( "Title" ) ); + QDomText titleTxt = doc->createTextNode( _title ); + title.appendChild( titleTxt ); + top.appendChild( title ); + + QDomElement description = doc->createElement( QString::fromLocal8Bit( "Description" ) ); + QDomText descriptionTxt = doc->createTextNode( _description ); + description.appendChild( descriptionTxt ); + top.appendChild( description ); + + top.appendChild( _child->toXml( doc ) ); + + return top; +} + + +bool CompoundRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit("Compound") ); + QString str = top.attribute( QString::fromLocal8Bit( "hidden" ), QString::fromLocal8Bit("0") ); + _hidden = true; // alway hidden. (str == QString::fromLocal8Bit("1") ); + + str = top.attribute( QString::fromLocal8Bit( "allowReplace" ), QString::fromLocal8Bit("0") ); + _allowReplace = (str == QString::fromLocal8Bit("1") ); + + for ( QDomNode node = top.firstChild(); !node.isNull(); node = node.nextSibling() ) { + if ( !node.isElement() ) + continue; // skip past comments. + QString txt; + QDomElement child = node.toElement(); + QDomNode txtNode = child.firstChild(); + if ( txtNode.isText() ) + txt = txtNode.toText().data(); + if ( child.tagName() == QString::fromLocal8Bit( "Title" ) ) { + if ( txt.isEmpty() ) + _title = txt; + else + _title = i18n(txt.utf8()); + } + else if ( child.tagName() == QString::fromLocal8Bit( "Description" ) ) { + if ( txt.isEmpty() ) + _description = txt; + else + _description = i18n(txt.utf8()); + } + else { + _child = WidgetFactory::createRegExp( child, version ); + if ( _child ) { + addChild( _child ); + return true; + } + else { + return false; + } + } + } + return false; +} + +bool CompoundRegExp::operator==( const RegExp& other ) const +{ + // Note the order is important in the comparison below. + // Using other as the first argument, means that + // the following will be evaluated: other.operator== rather than (*child).operator== + // This means that if other is a CompoundRegExp too, then this level will be striped. + return ( other == *_child ); +} diff --git a/kregexpeditor/compoundregexp.h b/kregexpeditor/compoundregexp.h new file mode 100644 index 0000000..4e9aa8c --- /dev/null +++ b/kregexpeditor/compoundregexp.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef COMPOUNDREGEXP_H +#define COMPOUNDREGEXP_H +#include "regexp.h" + +/** + Abstract syntax node for `compound content' regular expression + @internal +*/ +class CompoundRegExp :public RegExp +{ +public: + CompoundRegExp( bool selected, const QString& title = QString::null, + const QString& description = QString::null, + bool hidden = false, bool allowReplace = false, RegExp* child = 0); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return _child->precedence();} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + QString title() const { return _title; } + QString description() const { return _description; } + RegExp* child() const { return _child; } + bool hidden() const { return _hidden; } + bool allowReplace() const { return _allowReplace; } + virtual RegExpType type() const { return COMPOUND;} + virtual bool operator==( const RegExp& other ) const; + +private: + QString _title; + QString _description; + bool _hidden; + bool _allowReplace; + RegExp* _child; +}; + + +#endif // COMPOUNDREGEXP_H diff --git a/kregexpeditor/compoundwidget.cpp b/kregexpeditor/compoundwidget.cpp new file mode 100644 index 0000000..3294313 --- /dev/null +++ b/kregexpeditor/compoundwidget.cpp @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include <klocale.h> + #include <kdialogbase.h> + #include <kiconloader.h> + #include "compoundwidget.moc" +#endif + +#include "compoundwidget.h" +#include <qlayout.h> +#include <qcursor.h> +#include <qlineedit.h> +#include <qpainter.h> +#include <qtooltip.h> +#include "concwidget.h" +#include "kwidgetstreamer.h" +#include "qcheckbox.h" + +//================================================================================ + +CompoundDetailWindow::CompoundDetailWindow( QWidget* parent, const char* name ) + :QWidget( parent, name ) +{ + QVBoxLayout* layout = new QVBoxLayout( this ); + layout->setAutoAdd( true ); + + QLabel* label = new QLabel( i18n("&Title:"), this); + _title = new QLineEdit( this ); + label->setBuddy( _title ); + + label = new QLabel( i18n("&Description:"), this ); + _description = new QMultiLineEdit( this ); + label->setBuddy( _description ); + + _allowReplace = new QCheckBox( i18n("&Automatically replace using this item"), this ); + QToolTip::add( _allowReplace, i18n("When the content of this box is typed in to the ASCII line,<br>" + "this box will automatically be added around it,<br>" + "if this check box is selected.") ); + _allowReplace->setChecked( true ); + + _title->setFocus(); + +} + +QString CompoundDetailWindow::title() const +{ + return _title->text(); +} + +QString CompoundDetailWindow::description() const +{ + return _description->text(); +} + +bool CompoundDetailWindow::allowReplace() const +{ + return _allowReplace->isChecked(); +} + +void CompoundDetailWindow::setTitle( QString txt ) +{ + _title->setText( txt ); +} + +void CompoundDetailWindow::setDescription( QString txt ) +{ + _description->setText( txt ); +} + +void CompoundDetailWindow::setAllowReplace( bool b ) +{ + _allowReplace->setChecked( b ); +} + +//================================================================================ + +CompoundWidget::CompoundWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + const char* name ) + :SingleContainerWidget( editorWindow, parent, name == 0 ? "CompoundWidget" : name ) +{ + _child = new ConcWidget( editorWindow, this ); + init(); +} + +CompoundWidget::CompoundWidget( CompoundRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + : SingleContainerWidget( editorWindow, parent, name == 0 ? "CompoundWidget" : name ) +{ + init(); + _content->setTitle( regexp->title() ); + _content->setDescription( regexp->description() ); + _content->setAllowReplace( regexp->allowReplace() ); + RegExpWidget* child = WidgetFactory::createWidget( regexp->child(), _editorWindow, this ); + if ( !( _child = dynamic_cast<ConcWidget*>(child) ) ) { + _child = new ConcWidget( _editorWindow, child, this ); + } + + _hidden = regexp->hidden(); +} + +void CompoundWidget::init( ) +{ + _configWindow = new KDialogBase( this, "_configWindow", true, + i18n("Configure Compound"), + KDialogBase::Ok | KDialogBase::Cancel ); + _content = new CompoundDetailWindow( _configWindow ); + _configWindow->setMainWidget( _content ); + + connect( _configWindow, SIGNAL(cancelClicked()), this, SLOT(slotConfigCanceled())) ; + connect(_configWindow, SIGNAL(finished()), this, SLOT(slotConfigWindowClosed())); + + _down = getIcon( QString::fromLocal8Bit( "1downarrow" )); + _up = getIcon( QString::fromLocal8Bit( "1uparrow" ) ); + + _hidden = false; + _backRefId = -1; +} + +QSize CompoundWidget::sizeHint() const +{ + QFontMetrics metrics = fontMetrics(); + _childSize = _child->sizeHint(); + _textSize = metrics.size( 0, _content->title() ); + + int width, height; + + if ( _hidden ) { + _pixmapSize = _up.size(); + width = 2*pw + QMAX( 2*bdSize+_textSize.width(), 2*bdSize+_pixmapSize.width()); + height = _pixmapSize.height() + 2*bdSize + _textSize.height()+pw; + } + else { + _pixmapSize = _down.size(); + int headerLineWidth = 2*pw + 2*bdSize + _pixmapSize.width(); + if ( _textSize.width() != 0) + headerLineWidth += 3*bdSize + _textSize.width(); + + width = QMAX( 2*pw + _childSize.width(), headerLineWidth ); + height = QMAX( _textSize.height(), _pixmapSize.height() ) + + 2*bdSize + _childSize.height() + pw; + } + return QSize( width, height ); + +} + +void CompoundWidget::paintEvent( QPaintEvent *e ) +{ + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize); + + int horLineY, childY; + + // draw top line + if ( _hidden ) { + horLineY = _pixmapSize.height()/2; + childY = _pixmapSize.height() + bdSize; + _pixmapPos = QPoint( mySize.width()-pw-bdSize-_pixmapSize.width(), 0 ); + painter.drawLine( pw, horLineY, _pixmapPos.x(), horLineY ); + painter.drawLine( mySize.width() - bdSize - pw, horLineY, + mySize.width(), horLineY); + painter.drawPixmap( _pixmapPos, _up ); + } + else { + int maxH = QMAX( _textSize.height(), _pixmapSize.height() ); + int offset = 0; + horLineY = maxH/2; + childY = maxH+bdSize; + + painter.drawLine(pw, horLineY, bdSize, horLineY); + if ( _textSize.width() != 0 ) { + offset += pw + 2*bdSize; + + painter.drawText(offset, horLineY-_textSize.height()/2, + bdSize+_textSize.width(), horLineY+_textSize.height()/2, + 0, _content->title()); + offset += _textSize.width() + bdSize; + } + + _pixmapPos = QPoint( mySize.width()-pw-bdSize-_pixmapSize.width(), + horLineY - _pixmapSize.height()/2 ); + + painter.drawLine( offset, horLineY, _pixmapPos.x(), horLineY ); + painter.drawPixmap( _pixmapPos, _down ); + + painter.drawLine( mySize.width()-bdSize-pw, horLineY, mySize.width(), horLineY ); + } + + // draw rest frame + painter.drawLine(0, horLineY, 0, mySize.height() ); + painter.drawLine( mySize.width()-pw, horLineY, mySize.width()-pw, mySize.height() ); + painter.drawLine( 0, mySize.height()-pw, mySize.width(), mySize.height()-pw ); + + // place/size child + if ( _hidden ) { + _child->hide(); + painter.drawText( pw+bdSize, childY, + pw+bdSize+_textSize.width(), childY+_textSize.height(), 0, + _content->title() ); + } + else { + QSize curSize = _child->size(); + QSize newSize = QSize( QMAX( _child->sizeHint().width(), mySize.width()-2*pw), + _child->sizeHint().height()); + + _child->move( pw, childY ); + if ( curSize != newSize ) { + _child->resize(newSize); + // I resized the child, so give it a chance to relect thus. + _child->update(); + } + + _child->show(); + } + + RegExpWidget::paintEvent( e ); +} + +void CompoundWidget::slotConfigWindowClosed() +{ + _editorWindow->updateContent( 0 ); + update(); +} + +void CompoundWidget::slotConfigCanceled() +{ + QDataStream stream( _backup, IO_ReadOnly ); + KWidgetStreamer streamer; + streamer.fromStream( stream, _content ); + repaint(); +} + +RegExp* CompoundWidget::regExp() const +{ + return new CompoundRegExp( isSelected(), _content->title(), _content->description(), + _hidden, _content->allowReplace(), _child->regExp() ); +} + +void CompoundWidget::mousePressEvent( QMouseEvent* event ) +{ + if ( event->button() == LeftButton && + QRect( _pixmapPos, _pixmapSize ).contains( event->pos() ) ) { + // Skip otherwise we will never see the mouse release + // since it is eaten by Editor window. + } + else + SingleContainerWidget::mousePressEvent( event ); +} + +void CompoundWidget::mouseReleaseEvent( QMouseEvent* event) +{ + if ( event->button() == LeftButton && + QRect( _pixmapPos, _pixmapSize ).contains( event->pos() ) ) { + _hidden = !_hidden; + _editorWindow->updateContent( 0 ); + repaint(); // is this necesary? + _editorWindow->emitChange(); + } + else + SingleContainerWidget::mouseReleaseEvent( event ); +} + +bool CompoundWidget::updateSelection( bool parentSelected ) +{ + if ( _hidden ) { + bool changed = RegExpWidget::updateSelection( parentSelected ); + _child->selectWidget( _isSelected ); + if (changed) + repaint(); + return changed; + } + else { + return SingleContainerWidget::updateSelection( parentSelected ); + } +} + +int CompoundWidget::edit() +{ + _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width()/2, + _configWindow->sizeHint().height()/2) ); + QDataStream stream( _backup, IO_WriteOnly ); + KWidgetStreamer streamer; + streamer.toStream( _content, stream ); + return _configWindow->exec(); +} + +int nextId() +{ + static int counter = 0; + return ++counter; +} + +QPixmap CompoundWidget::getIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage(name) ); + return pix; +#else + return SmallIcon( name ); +#endif +} + + diff --git a/kregexpeditor/compoundwidget.h b/kregexpeditor/compoundwidget.h new file mode 100644 index 0000000..f757c05 --- /dev/null +++ b/kregexpeditor/compoundwidget.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef compoundwidget +#define compoundwidget +class QLineEdit; +class QMultiLineEdit; +class KDialogBase; +class QCheckBox; + +#include "singlecontainerwidget.h" +#include "compoundregexp.h" + +/** + Widget containing configuration details for @ref CompoundWidget + @internal +*/ +class CompoundDetailWindow :public QWidget +{ +public: + CompoundDetailWindow(QWidget* parent, const char* name = 0); + QString title() const; + QString description() const; + bool allowReplace() const; + void setTitle( QString ); + void setDescription( QString ); + void setAllowReplace( bool ); + +private: + QLineEdit* _title; + QMultiLineEdit* _description; + QCheckBox* _allowReplace; +}; + + +/** + Comopund RegExp widget. + + This widget has two purposes: + @li To make it possible for a user to collapse a huge regular expression + to take up less screen space. + @li To act as back references for later use. + + @internal +*/ +class CompoundWidget :public SingleContainerWidget +{ +Q_OBJECT + +public: + CompoundWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + const char* name = 0); + CompoundWidget( CompoundRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + + virtual bool updateSelection( bool parentSelected ); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return COMPOUND; } + virtual int edit(); + +protected: + virtual void paintEvent( QPaintEvent *e ); + virtual void mousePressEvent( QMouseEvent* e ); + virtual void mouseReleaseEvent( QMouseEvent* e); + void init(); + QPixmap getIcon( const QString& name ); + +protected slots: + void slotConfigCanceled(); + void slotConfigWindowClosed(); + +private: + bool _hidden; + QPixmap _up, _down; + mutable QSize _pixmapSize; + mutable QPoint _pixmapPos; + + KDialogBase* _configWindow; + CompoundDetailWindow* _content; + + mutable QSize _textSize; + mutable QSize _childSize; + QByteArray _backup; + + int _backRefId; +}; + + +#endif // compoundwidget diff --git a/kregexpeditor/concregexp.cpp b/kregexpeditor/concregexp.cpp new file mode 100644 index 0000000..4fac8d0 --- /dev/null +++ b/kregexpeditor/concregexp.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "concregexp.h" +#include "widgetfactory.h" +#include "compoundregexp.h" + +ConcRegExp::ConcRegExp( bool selected ) :RegExp( selected ) +{ +} + +void ConcRegExp::addRegExp( RegExp *regExp ) +{ + list.append(regExp); + addChild( regExp ); +} + +RegExpList ConcRegExp::children() +{ + return list; +} + + +bool ConcRegExp::check( ErrorMap& map, bool first, bool last) +{ + bool f = first; + bool possibleEmpty = true; + for ( RegExpListIt it(list); *it; ++it ) { + possibleEmpty = (*it)->check( map, f, last && it.atLast() ) && possibleEmpty; + if ( ! possibleEmpty ) + f = false; + } + return possibleEmpty; +} + +RegExp* ConcRegExp::lastRegExp() +{ + if ( list.count() == 0) + return 0; + else + return list.at( list.count()-1); +} + +QDomNode ConcRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit("Concatenation") ); + for ( RegExpListIt it(list); *it; ++it ) { + top.appendChild( (*it)->toXml( doc ) ); + } + return top; +} + +bool ConcRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Concatenation" ) ); + + for ( QDomNode child = top.firstChild(); !child.isNull(); child = child.nextSibling() ) { + if ( ! child.isElement() ) + continue; // User might have added a comment. + + RegExp* regexp = WidgetFactory::createRegExp( child.toElement(), version ); + if ( regexp == 0 ) + return false; + addRegExp( regexp ); + } + return true; +} + +bool ConcRegExp::operator==( const RegExp& other ) const +{ + // TODO: Merge with AltnRegExp::operator== + if ( list.count() == 1 ) + return ( other == *(const_cast< QPtrList<RegExp>& >(list).at(0)) ); + + if ( other.type() != type() ) + return false; + + const ConcRegExp& theOther = dynamic_cast<const ConcRegExp&>( other ); + + if ( list.count() != theOther.list.count() ) + return false; + + RegExpListIt it1( list ); + RegExpListIt it2( theOther.list ); + + for ( ; *it1 && *it2 ; ) { + if ( ! (**it1 == **it2) ) + return false; + ++it1; + ++it2; + } + return true; +} + + +void ConcRegExp::replacePart( CompoundRegExp* replacement ) +{ + RegExp* otherChild = replacement->child(); + ConcRegExp* otherConc = dynamic_cast<ConcRegExp*>( otherChild ); + if ( ! otherConc ) { + // Watch out for garbage here! + otherConc = new ConcRegExp( false ); + otherConc->addRegExp( otherChild ); + } + + RegExpList newList; + RegExpListIt it1( list ); + while ( *it1 ) { + (*it1)->replacePart( replacement ); + RegExpListIt it2 = it1; + RegExpListIt it3( otherConc->list ); + bool match = true; + int count = 0; + + // See if replacement is a sublist of list starting from what it1 points at + for ( ; *it2 && * it3 && match ; ) { + if (! ( **it2 == **it3 ) ) + match = false; + ++it2; + ++it3; + ++count; + } + + if ( match && ! *it3) { + // I found a match, delete the element in it1, which is common with it3 + while ( *it1 != *it2 ) { + RegExp* item = *it1; + ++it1; + delete item; + } + RegExp* theClone = replacement->clone(); + newList.append( theClone ); + addChild( theClone ); + } + else { + newList.append( *it1 ); + ++it1; + } + } + list = newList; +} + + diff --git a/kregexpeditor/concregexp.h b/kregexpeditor/concregexp.h new file mode 100644 index 0000000..52a6342 --- /dev/null +++ b/kregexpeditor/concregexp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __CONCREGEXP_H +#define __CONCREGEXP_H + +#include "regexp.h" + + +/** + Abstract syntax node for `concatenated' regular expression + @internal +*/ +class ConcRegExp :public RegExp +{ +public: + ConcRegExp( bool selected ); + + void addRegExp( RegExp *); + RegExpList children(); + RegExp* lastRegExp(); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 2;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const {return CONC; } + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ); + +private: + RegExpList list; +}; + +#endif // __CONCREGEXP_H diff --git a/kregexpeditor/concwidget.cpp b/kregexpeditor/concwidget.cpp new file mode 100644 index 0000000..f67c49b --- /dev/null +++ b/kregexpeditor/concwidget.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "concregexp.h" +#include "concwidget.h" +#include "dragaccepter.h" + +#include <qpainter.h> + +ConcWidget::ConcWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + :MultiContainerWidget(editorWindow, parent, name == 0 ? "concwidget" : name) +{ + init(); + DragAccepter *accepter = new DragAccepter(editorWindow, this); + accepter->show(); + _children.append(accepter); +} + + +ConcWidget::ConcWidget(RegExpEditorWindow* editorWindow, RegExpWidget *child, + QWidget *parent, const char *name) + :MultiContainerWidget(editorWindow, parent, name == 0 ? "concwidget" : name) +{ + init(); + DragAccepter *accepter = new DragAccepter(editorWindow, this); + _children.append(accepter); + child->reparent(this, QPoint(0,0), false); + addNewChild(accepter, child); +} + +ConcWidget::ConcWidget( RegExpEditorWindow* editorWindow, ConcWidget* origConc, + unsigned int start, unsigned int end) + :MultiContainerWidget(editorWindow, 0, "Splitted ConcWidget") +{ + init(); + _children.prepend( new DragAccepter(editorWindow, this) ); + for (unsigned int i = end; i >= start; i--) { + RegExpWidget* child = origConc->_children.take( i ); + _children.prepend( child ); + child->reparent( this, QPoint(0,0), false); + } + _children.prepend( new DragAccepter(editorWindow, this) ); +} + +ConcWidget::ConcWidget( ConcRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + :MultiContainerWidget( editorWindow, parent, name == 0 ? "concwidget" : name ) +{ + init(); + DragAccepter *accepter = new DragAccepter(editorWindow, this); + _children.append(accepter); + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + RegExpWidget* child = WidgetFactory::createWidget( *it, editorWindow, this ); + append( child ); + } +} + +void ConcWidget::init() +{ + _maxSelectedHeight = 0; +} + + +QSize ConcWidget::sizeHint() const +{ + int childrenWidth = 0; + int childrenHeight = 0; + QPtrListIterator<RegExpWidget> it(_children); + + for ( ; *it; ++it) { + QSize thisChildSize = (*it)->sizeHint(); + childrenWidth += thisChildSize.width(); + childrenHeight = QMAX(childrenHeight, thisChildSize.height()); + } + + return QSize(childrenWidth, childrenHeight); +} + +void ConcWidget::paintEvent( QPaintEvent *e) +{ + Q_ASSERT( dynamic_cast<DragAccepter*>(_children.at(0)) ); + // if this fails, then I should check the location of the show() + Q_ASSERT( _children.count() == 1 || + ( _children.count() >=3 && + dynamic_cast<DragAccepter*>(_children.at(_children.count()-1)) ) ); + + if ( _children.count() == 1) { + // There is only an accepter, lets give it all the space. + _children.at(0)->setGeometry( 0, 0, size().width(), size().height() ); + } + else { + QSize myReqSize = sizeHint(); + QSize mySize(QMAX(myReqSize.width(), size().width()), + QMAX(myReqSize.height(), size().height())); + + // If the widget needs less space than it can get then this space should + // be given to the leftmost and rightmost accepter. So lets calculate + // this extra space. + int extra = 0; + if (size().width() > myReqSize.width()) { + extra = (size().width() - myReqSize.width())/2; + } + + QPainter painter( this ); + + drawPossibleSelection( painter, mySize ); + + int lastHeight = 0; + int offset = 0; + + for (unsigned int i = 1; i < _children.count(); i += 2 ) { + DragAccepter* accepter = dynamic_cast<DragAccepter*>(_children.at(i-1)); + if (!accepter) + continue; + RegExpWidget* child = _children.at(i); + + QSize childSize = child->sizeHint(); + QSize curChildSize = child->size(); + + //----------------------------- first place the accepter + int x = offset; + int w = accepter->sizeHint().width(); + if ( i == 1 ) w+= extra; + int h = QMAX( lastHeight, childSize.height() ); + int y = (mySize.height() - h)/2; + accepter->setGeometry( x, y, w, h ); + + offset += w; + lastHeight = childSize.height(); + + + //------------------------------ Draw Accepter selection + if ( accepter->isSelected() ) { + y = (mySize.height()-_maxSelectedHeight)/2; + h = _maxSelectedHeight; + painter.fillRect( x, y, w, h, QBrush( gray ) ); + } + + //-------------------------------------- place the child + x = offset; + h = childSize.height(); + w = childSize.width(); + y = (mySize.height() - h)/2; + child->setGeometry( x, y, w, h ); + if ( childSize != curChildSize ) { + // I resized the child, so give it a chance to relect thus. + child->update(); + } + + offset += w; + + //------------------------------ Draw Accepter selection + if ( child->isSelected() ) { + y = (mySize.height()-_maxSelectedHeight)/2; + h = _maxSelectedHeight; + painter.fillRect( x, y, w, h, QBrush( gray ) ); + } + } + + //---------------------- Finally place the last accepter. + DragAccepter* accepter = + dynamic_cast<DragAccepter*>(_children.at(_children.count()-1)); + // dynamic_cast is ASSERTed at top + int x = offset; + int h = lastHeight; + int w = accepter->sizeHint().width() + extra; + int y = (mySize.height()-h)/2; + accepter->setGeometry( x, y, w, h ); + } + MultiContainerWidget::paintEvent( e ); +} + +void ConcWidget::mousePressEvent ( QMouseEvent* event ) +{ + if ( event->button() == RightButton ) { + _editorWindow->showRMBMenu( _editorWindow->hasSelection() ); + } + else { + RegExpWidget::mousePressEvent( event ); + } +} + + + +void ConcWidget::sizeAccepter( DragAccepter* accepter, int height, int totHeight ) +{ + if (accepter->height() != height ) { + accepter->resize( accepter->width(), height ); + } + + if (accepter->y() != (totHeight - height)/2) { + accepter->move( accepter->x(), (totHeight - height)/2 ); + } +} + +RegExp* ConcWidget::regExp() const +{ + QPtrListIterator<RegExpWidget> it( _children ); + ++it; // start with the second element. + + if ( _children.count() == 3 ) { + // Exactly one child (and two drag accepters) + return (*it)->regExp(); + } + else { + ConcRegExp *regexp = new ConcRegExp( isSelected() ); + + for ( ; *it; it+=2 ) { + regexp->addRegExp( (*it)->regExp() ); + } + return regexp; + } +} + +bool ConcWidget::updateSelection(bool parentSelected) +{ + bool isSel = _isSelected; + bool changed = MultiContainerWidget::updateSelection( parentSelected ); + + _maxSelectedHeight = 0; + + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Skip past the first DragAccepter + for ( ; *it; it +=2 ) { + if ( (*it)->isSelected() ) { + _maxSelectedHeight = QMAX( _maxSelectedHeight, (*it)->sizeHint().height() ); + } + } + + changed = changed || isSel != _isSelected; + if ( changed ) { + repaint(); + } + + return changed; +} + +void ConcWidget::getSelectionIndexes( int* start, int* end ) +{ + *start = -1; + *end = -1; + + // Start with element at index 1, and skip every second element, as we + // know they are dragAccepters. + for ( unsigned int index = 1; index< _children.count(); index += 2 ) { + RegExpWidget* child = _children.at(index); + + if ( child->isSelected() ) { + // The child is selected at topmost level. + if ( *start == -1 ) { + *start = index; + } + } + else if ( *start != -1 ) { + // Found the end of the selection. + *end = index -2; + break; + } + } + + if ( *start != -1 && *end == -1 ) + *end = _children.count() -2; +} + +void ConcWidget::applyRegExpToSelection( RegExpType type ) +{ + int start, end; + getSelectionIndexes( &start, &end ); + + if ( start == -1 ) { + // No item selected at top level + + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Skip past the first DragAccepter + for ( ; *it ; it += 2 ) { + if ( (*it)->hasSelection() ) { + (*it)->applyRegExpToSelection( type ); + break; + } + } + } + else { + // Apply RegExp to selection. + RegExpWidget* newElm = WidgetFactory::createWidget( _editorWindow, this, type ); + + if ( newElm ) { + ConcWidget* subSequence = new ConcWidget(_editorWindow, this, start, end); + newElm->setConcChild( subSequence ); + + + subSequence->resize(0,0); // see note (1) + subSequence->reparent( newElm, QPoint(0,0), false); + _children.insert( start, newElm ); + newElm->show(); + } + } +} + +bool ConcWidget::isSelected() const +{ + // A ConcWidget should be considered selected when all its elements has been selected + // otherwise empty ConcWidgets may be left behind when for example selection is deleted. + bool allSelected = true; + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Skip past first DragAccepter. + for ( ; *it && allSelected; it += 2 ) { + allSelected = allSelected && (*it)->isSelected(); + } + + return allSelected; +} + +RegExp* ConcWidget::selection() const +{ + if ( isSelected() ) + return regExp(); + + bool foundAny = false; + bool foundMoreThanOne = false; + RegExp* regexp = 0; + + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Skip past the first DragAccepter + for ( ; (*it) ; it += 2 ) { + if ( (*it)->hasSelection() ) { + if (!foundAny) { + regexp = (*it)->selection(); + foundAny = true; + } + else if ( !foundMoreThanOne ) { + ConcRegExp* reg = new ConcRegExp( isSelected() ); + reg->addRegExp( regexp ); + reg->addRegExp( (*it)->selection() ); + regexp = reg; + foundMoreThanOne = true; + } + else { + dynamic_cast<ConcRegExp*>(regexp)->addRegExp( (*it)->selection() ); + } + } + } + + Q_ASSERT( foundAny ); + return regexp; +} + +void ConcWidget::addNewConcChild(DragAccepter *accepter, ConcWidget *other) +{ + for ( unsigned int i=0; i<_children.count(); i+= 2 ) { + RegExpWidget *ch = _children.at( i ); + if ( ch == accepter ) { + // Move all the element from the `child' ConcWidget to this one. + // Do not copy the first one as this is a dragAccepter, and we place the widgets + // after this drag accepter. + // We must take them in pairs to avoid breaking the invariant for paintEvent, + // namely that every second element is a dragAccepter + for ( unsigned int j = other->_children.count()-1; j > 0 ; j-=2 ) { + RegExpWidget* newChildA = other->_children.take(j); + newChildA->reparent( this, QPoint(0,0), false); + _children.insert( i+1, newChildA ); + RegExpWidget* newChildB = other->_children.take(j-1); + newChildB->reparent( this, QPoint(0,0), false); + _children.insert( i+1, newChildB ); + newChildA->show(); + newChildB->show(); + } + delete other; + return; + } + } + qFatal("accepter not found"); +} + +bool ConcWidget::validateSelection() const +{ + bool cont = true; + QPtrListIterator<RegExpWidget> it(_children); + ++it; // skip past the DragAccepter. + for ( ; *it && cont; it += 2 ) { + cont = (*it)->validateSelection(); + } + return cont; +} diff --git a/kregexpeditor/concwidget.h b/kregexpeditor/concwidget.h new file mode 100644 index 0000000..6101ed2 --- /dev/null +++ b/kregexpeditor/concwidget.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __concwidget +#define __concwidget + +#include "multicontainerwidget.h" +class ConcRegExp; + +/** + RegExp widget which can have several sub widget inside it. + This widget is invisible to the user, but act as a container around + other RegExp widgets + @internal +*/ +class ConcWidget :public MultiContainerWidget +{ +public: + ConcWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + ConcWidget(RegExpEditorWindow* editorWindow, RegExpWidget *child, + QWidget *parent, const char *name=0); + ConcWidget( RegExpEditorWindow* editorWindow, ConcWidget* origConc, + unsigned int start, unsigned int end); + ConcWidget( ConcRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + void init(); + + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual bool updateSelection(bool parentSelected); + virtual bool isSelected() const; + + virtual void applyRegExpToSelection( RegExpType type ); + virtual RegExpType type() const { return CONC; } + virtual RegExp* selection() const; + virtual void addNewConcChild(DragAccepter *accepter, ConcWidget *child); + virtual bool validateSelection() const; + virtual bool acceptWidgetInsert( RegExpType ) const { return false; } + virtual bool acceptWidgetPaste() const { return false; } + bool hasAnyChildren() { return _children.count() > 1; } + +protected: + virtual void paintEvent( QPaintEvent *e ); + virtual void mousePressEvent ( QMouseEvent* event ); + void sizeAccepter( DragAccepter* accepter, int height, int totHeight ); + void getSelectionIndexes( int* start, int* end ); + virtual void dragEnterEvent(QDragEnterEvent* event) { event->accept( false ); } + +private: + int _maxSelectedHeight; +}; + + +#endif // __concwidget diff --git a/kregexpeditor/dcbutton.cpp b/kregexpeditor/dcbutton.cpp new file mode 100644 index 0000000..b5bdcf8 --- /dev/null +++ b/kregexpeditor/dcbutton.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include "dcbutton.moc" +#endif + +#include "dcbutton.h" + +DoubleClickButton::DoubleClickButton( QPixmap pixmap, QWidget* parent, const char* name ) + : QToolButton( parent, name ? name : "DoubleClickButton" ) +{ + setPixmap( pixmap ); +} + +void DoubleClickButton::mouseDoubleClickEvent( QMouseEvent* ) +{ + emit doubleClicked(); +} + + diff --git a/kregexpeditor/dcbutton.h b/kregexpeditor/dcbutton.h new file mode 100644 index 0000000..78a18a3 --- /dev/null +++ b/kregexpeditor/dcbutton.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef dcbutton +#define dcbutton + +#include <qtoolbutton.h> +class QMouseEvent; + +/** + QToolButton extended to emit a signal on double click. + @internal +*/ +class DoubleClickButton :public QToolButton +{ +Q_OBJECT + +public: + DoubleClickButton( QPixmap pix, QWidget* parent, const char* name = 0); + +protected: + virtual void mouseDoubleClickEvent ( QMouseEvent * ); + +signals: + void doubleClicked(); +}; + +#endif // dcbutton diff --git a/kregexpeditor/dotregexp.cpp b/kregexpeditor/dotregexp.cpp new file mode 100644 index 0000000..3d375be --- /dev/null +++ b/kregexpeditor/dotregexp.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "dotregexp.h" + +DotRegExp::DotRegExp( bool selected ) :RegExp( selected ) +{ +} + +bool DotRegExp::check( ErrorMap&, bool, bool ) +{ + return false; +} + +QDomNode DotRegExp::toXml( QDomDocument* doc ) const +{ + return doc->createElement( QString::fromLocal8Bit("AnyChar") ); +} + +bool DotRegExp::load( QDomElement /* top */, const QString& /*version*/ ) +{ + // Nothing to do + return true; +} + diff --git a/kregexpeditor/dotregexp.h b/kregexpeditor/dotregexp.h new file mode 100644 index 0000000..b46cffb --- /dev/null +++ b/kregexpeditor/dotregexp.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef DOTREGEXP_H +#define DOTREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for "the dot" regular expression (i.e. any characters) + @internal +*/ +class DotRegExp :public RegExp +{ +public: + + DotRegExp( bool selected ); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return DOT;} +}; + +#endif // DOTREGEXP_H + diff --git a/kregexpeditor/drag.cpp b/kregexpeditor/drag.cpp new file mode 100644 index 0000000..11ecc63 --- /dev/null +++ b/kregexpeditor/drag.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "drag.h" +#include "regexp.h" +#include "regexpconverter.h" +#include "widgetfactory.h" + +RegExpWidgetDrag::RegExpWidgetDrag( RegExp* regexp, QWidget* dragSource ) + : QDragObject( dragSource ), _regexp( regexp->clone() ) +{ +} + +RegExpWidgetDrag::~RegExpWidgetDrag() +{ + delete _regexp; +} + + +bool RegExpWidgetDrag::canDecode( QDragMoveEvent* event ) +{ + return event->provides( "KRegExpEditor/widgetdrag" ); +} + +RegExpWidget* RegExpWidgetDrag::decode(QDropEvent* event, RegExpEditorWindow* window, + QWidget* parent) +{ + QByteArray payload = event->encodedData("KRegExpEditor/widgetdrag" ); + QTextStream stream( payload, IO_ReadOnly ); + QString str = stream.read(); + RegExp* regexp = WidgetFactory::createRegExp( str ); + RegExpWidget* widget = WidgetFactory::createWidget( regexp, window, parent ); + delete regexp; + return widget; +} + +const char * RegExpWidgetDrag::format ( int i ) const +{ + if ( i == 0 ) + return "KRegExpEditor/widgetdrag"; + else if ( i == 1 ) + return "text/plain"; + else + return 0; +} + +QByteArray RegExpWidgetDrag::encodedData ( const char* format ) const +{ + QByteArray data; + QTextStream stream( data, IO_WriteOnly ); + if ( QString::fromLocal8Bit( format ).startsWith(QString::fromLocal8Bit( "KRegExpEditor/widgetdrag" ) ) ) { + QString xml = _regexp->toXmlString(); + stream << xml; + } + else if ( QString::fromLocal8Bit( format ).startsWith(QString::fromLocal8Bit( "text/plain" ) ) ) { + stream << RegExpConverter::current()->toStr( _regexp, false ); + } + else { + qWarning("Unexpected drag and drop format: %s", format ); + } + return data; +} + diff --git a/kregexpeditor/drag.h b/kregexpeditor/drag.h new file mode 100644 index 0000000..5a074d1 --- /dev/null +++ b/kregexpeditor/drag.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef drag_h +#define drag_h + +#include <qdragobject.h> + +class RegExp; +class RegExpWidget; +class RegExpEditorWindow; + +/** + Class used for drag and drop in the RegExp widget. + @internal +*/ +class RegExpWidgetDrag :public QDragObject +{ +public: + RegExpWidgetDrag( RegExp* regexp , QWidget* dragSource); + ~RegExpWidgetDrag(); + virtual const char * format ( int i = 0 ) const; + virtual QByteArray encodedData ( const char * ) const; + static bool canDecode(QDragMoveEvent* event); + static RegExpWidget* decode(QDropEvent* event, RegExpEditorWindow* window, + QWidget* parent); +private: + RegExp* _regexp; +}; + +#endif // drag_h diff --git a/kregexpeditor/dragaccepter.cpp b/kregexpeditor/dragaccepter.cpp new file mode 100644 index 0000000..0198e58 --- /dev/null +++ b/kregexpeditor/dragaccepter.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "dragaccepter.h" +#include "concwidget.h" + +#include <qpainter.h> + +DragAccepter::DragAccepter(RegExpEditorWindow* editorWindow, RegExpWidget *parent, + const char *name) + : RegExpWidget(editorWindow, parent, name == 0 ? "dragaccepter" : name ), + _drawLine( false ) +{ + setAcceptDrops(TRUE); +} + +QSize DragAccepter::sizeHint() const +{ + return QSize(10,10); +} + +void DragAccepter::paintEvent(QPaintEvent *e) +{ + QPainter painter(this); + drawPossibleSelection( painter, size() ); + + if ( _drawLine ) + painter.drawLine( 0, height()/2, width(), height()/2 ); + + RegExpWidget::paintEvent(e); +} + +void DragAccepter::mousePressEvent ( QMouseEvent* event ) +{ + if ( event->button() == RightButton ) { + _editorWindow->showRMBMenu( _editorWindow->hasSelection() ); + } + else { + RegExpWidget::mousePressEvent( event ); + } +} + +void DragAccepter::mouseReleaseEvent( QMouseEvent* event ) +{ + if ( _editorWindow->isPasteing() && event->button() == LeftButton ) { + RegExp* regexp = _editorWindow->pasteData(); + + RegExpWidget *newElm = WidgetFactory::createWidget( regexp, _editorWindow, 0 ); + if ( newElm ) { + ConcWidget* elm; + if (! (elm = dynamic_cast<ConcWidget*>( newElm ) ) ) { + elm = new ConcWidget( _editorWindow, newElm, 0 ); + } + + Q_ASSERT( elm ); + + RegExpWidget *w = dynamic_cast<RegExpWidget*>(parent()); + if (w) + w->addNewConcChild(this, elm); + _editorWindow->updateContent( this ); + _editorWindow->clearSelection( true ); + } + } + else if ( _editorWindow->isInserting() && event->button() == LeftButton ) { + if ( WidgetFactory::isContainer( _editorWindow->insertType() ) && + _editorWindow->pointSelected( mapToGlobal( event->pos() ) ) ) { + RegExpWidget::mouseReleaseEvent( event ); + } + else { + RegExpWidget *child = WidgetFactory::createWidget( _editorWindow, + dynamic_cast<QWidget*>(parent()), + _editorWindow->insertType() ); + if ( child ) { + RegExpWidget *w = dynamic_cast<RegExpWidget*>(parent()); + if (w) + w->addNewChild(this, child); + _editorWindow->updateContent( child ); + child->setFocus(); + _editorWindow->clearSelection( true ); + } + } + } + _editorWindow->slotEndActions(); +} + + +void DragAccepter::dragEnterEvent(QDragEnterEvent *event) +{ + bool selfDrag = ( event->source() && event->source()->topLevelWidget() == topLevelWidget() && _isSelected ); + event->accept(RegExpWidgetDrag::canDecode( event ) && !selfDrag ); +} + +void DragAccepter::dropEvent(QDropEvent *event) +{ + // The widget will be reparent afterward or part of it will, so no need to give + // it a parent here. + RegExpWidget *newElm = RegExpWidgetDrag::decode( event, _editorWindow, 0 ); + ConcWidget* elm; + if ( !(elm = dynamic_cast<ConcWidget*>( newElm ) ) ) { + elm = new ConcWidget( _editorWindow, newElm, 0 ); + } + + Q_ASSERT( elm ); + + RegExpWidget *rew = dynamic_cast<RegExpWidget*>(parent()); + if (rew) + rew->addNewConcChild(this, elm); + QWidget *w = dynamic_cast<QWidget*>(parent()); + if (w) + w->update(); + _editorWindow->updateContent( this ); + + bool selfDrag = ( event->source() && event->source()->topLevelWidget() == topLevelWidget() ); + if ( ! selfDrag ) + _editorWindow->clearSelection( true ); + else { + // selection should not be cleared here, since we might want to delete it. + } + event->accept(); +} + +RegExp* DragAccepter::regExp() const +{ + return 0; +} diff --git a/kregexpeditor/dragaccepter.h b/kregexpeditor/dragaccepter.h new file mode 100644 index 0000000..48af09f --- /dev/null +++ b/kregexpeditor/dragaccepter.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __dragaccepter +#define __dragaccepter + +#include "regexpwidget.h" +class MultiContainerWidget; + +/** + RegExp widget representing a "spot" in which new RegExp widgets can be inserted. + @internal +*/ +class DragAccepter :public RegExpWidget +{ + friend class MultiContainerWidget; + +public: + DragAccepter(RegExpEditorWindow* editorWindow, RegExpWidget *parent, + const char *name = 0); + QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return DRAGACCEPTER; } + void setDrawLine( bool drawLine ) { _drawLine = drawLine; } + +protected: + virtual void mousePressEvent ( QMouseEvent* event ); + virtual void mouseReleaseEvent( QMouseEvent* event ); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + virtual void paintEvent(QPaintEvent *); + virtual bool acceptWidgetInsert( RegExpType ) const { return true; } + virtual bool acceptWidgetPaste() const { return true; } + +private: + bool _drawLine; +}; + +#endif // __dragaccepter diff --git a/kregexpeditor/editorwindow.cpp b/kregexpeditor/editorwindow.cpp new file mode 100644 index 0000000..e8c4ac8 --- /dev/null +++ b/kregexpeditor/editorwindow.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include <klocale.h> + #include <kmessagebox.h> +// #include <kfiledialog.h> + #include <kstandarddirs.h> + #include <kiconloader.h> + #include "editorwindow.moc" + #include <klineeditdlg.h> +#endif + +#include "editorwindow.h" +#include "concwidget.h" +#include <qlayout.h> +#include <qpainter.h> +#include <qaccel.h> +#include <qcursor.h> +#include <qclipboard.h> +#include <qpopupmenu.h> +#include "regexp.h" +#include "userdefinedregexps.h" +#include <qfileinfo.h> + +RegExpEditorWindow::RegExpEditorWindow( QWidget *parent, const char *name) + : QWidget(parent, name, Qt::WPaintUnclipped) +{ + _top = new ConcWidget(this, this); + _layout = new QHBoxLayout( this); + _layout->addWidget(_top); + _top->setToplevel(); + _undrawSelection = false; + _menu = 0; + _insertInAction = false; + _pasteInAction = false; + _pasteData = 0; + + QAccel* accel = new QAccel( this ); + accel->connectItem( accel->insertItem( CTRL+Key_C ), this, SLOT( slotCopy() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_X ), this, SLOT( slotCut() ) ); + accel->connectItem( accel->insertItem( Key_Delete ), this, SLOT( slotCut() ) ); + accel->connectItem( accel->insertItem( Key_BackSpace ), this, SLOT( slotCut() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_V ), this, SLOT( slotStartPasteAction() ) ); + accel->connectItem( accel->insertItem( Key_Escape ), this, SLOT( slotEndActions() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_S ), this, SLOT( slotSave() ) ); + + connect( this, SIGNAL( change() ), this, SLOT( emitVerifyRegExp() ) ); +} + +RegExp* RegExpEditorWindow::regExp() const +{ + return _top->regExp(); +} + +void RegExpEditorWindow::mousePressEvent ( QMouseEvent* event ) +{ + setFocus(); + updateContent( 0 ); + + _start = event->pos(); + _lastPoint = QPoint(0,0); + + if ( pointSelected( event->globalPos() ) ) { + _isDndOperation = true; + } + else { + _isDndOperation = false; + _selection = QRect(); + _top->updateSelection( false ); + + QWidget::mousePressEvent( event ); + } + grabMouse(); +} + +bool RegExpEditorWindow::pointSelected( QPoint p ) const +{ + QRect rect = _top->selectionRect(); + return rect.contains(p); +} + +void RegExpEditorWindow::mouseMoveEvent ( QMouseEvent* event ) +{ + if ( _isDndOperation ) { + if ( ( _start - event->pos() ).manhattanLength() > QApplication::startDragDistance() ) { + RegExp* regexp = _top->selection(); + if ( !regexp ) + return; + QDragObject *d = new RegExpWidgetDrag( regexp, this ); + delete regexp; + + bool del = d->drag(); + if ( del ) + slotDeleteSelection(); + else { + clearSelection( true ); + } + releaseMouse(); + emit change(); + emit canSave( _top->hasAnyChildren() ); + } + } + else { + QPainter p( this ); + p.setRasterOp( Qt::NotROP ); + p.setPen( Qt::DotLine ); + + // remove last selection rectangle + if ( ! _lastPoint.isNull() && _undrawSelection ) { + p.drawRect(QRect(_start, _lastPoint)); + } + + // Note this line must come after the old rect has been removed + // and before the new one is draw otherwise the update event which this + // line invokes, will remove a line, which later will be drawn instead of + // removed during NotROP. + _top->updateSelection( false ); + emit scrolling( event->pos() ); + + p.drawRect(QRect(_start, event->pos())); + _undrawSelection = true; + _lastPoint = event->pos(); + + _selection = QRect(mapToGlobal(_start), mapToGlobal(_lastPoint)).normalize(); + } +} + +void RegExpEditorWindow::mouseReleaseEvent( QMouseEvent *event) +{ + releaseMouse(); + QWidget::mouseReleaseEvent( event); + + // remove last selection rectangle + QPainter p( this ); + p.setRasterOp( Qt::NotROP ); + p.setPen( Qt::DotLine ); + if ( ! _lastPoint.isNull() ) { + p.drawRect(QRect(_start, _lastPoint)); + } + _top->validateSelection(); + _top->updateAll(); + emit anythingSelected( hasSelection() ); + if ( hasSelection() ) { + emit verifyRegExp(); + } +} + +bool RegExpEditorWindow::selectionOverlap( QPoint pos, QSize size ) const +{ + QRect child(pos, size); + + return (_selection.intersects(child) && ! child.contains(_selection)); +} + +bool RegExpEditorWindow::hasSelection() const +{ + return _top->hasSelection(); +} + +void RegExpEditorWindow::clearSelection( bool update ) +{ + _top->clearSelection(); + if ( update ) + _top->updateAll(); + emit anythingSelected(false); +} + +void RegExpEditorWindow::slotInsertRegExp( RegExpType type ) +{ + _insertInAction = true; + _insertTp = type; + + updateCursorUnderPoint(); + setFocus(); +} + +void RegExpEditorWindow::slotInsertRegExp( RegExp* regexp ) +{ + if ( _pasteData ) + delete _pasteData; + + _pasteData = regexp->clone(); + _pasteInAction = true; + updateCursorUnderPoint(); + setFocus(); +} + +void RegExpEditorWindow::slotDoSelect() +{ + _pasteInAction = false; + _insertInAction = false; + + // I need to update the cursor recursively, as a repaint may not have been issued yet + // when this method is invoked. This means that when the repaint comes, the cursor may + // move to an other widget. + _top->updateCursorRecursively(); +} + +void RegExpEditorWindow::slotDeleteSelection() +{ + if ( ! hasSelection() ) { + KMessageBox::information(this, i18n( "There is no selection."), i18n("Missing Selection") ); + } + else { + _top->deleteSelection(); + } + updateContent( 0 ); +} + +void RegExpEditorWindow::updateContent( QWidget* focusChild) +{ + QPoint p(0,0); + if ( focusChild ) + p = focusChild->mapTo( this, QPoint(0,0) ); + + _top->update(); + emit contentChanged( p ); +} + +QSize RegExpEditorWindow::sizeHint() const +{ + return _top->sizeHint(); +} + +void RegExpEditorWindow::paintEvent( QPaintEvent* event ) +{ + QWidget::paintEvent( event ); + _undrawSelection = false; +} + +void RegExpEditorWindow::slotCut() +{ + cut( QCursor::pos() ); + emit change(); + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::cut( QPoint pos ) +{ + cutCopyAux( pos ); + slotDeleteSelection(); +} + +void RegExpEditorWindow::slotCopy() +{ + copy( QCursor::pos() ); +} + +void RegExpEditorWindow::copy( QPoint pos ) +{ + cutCopyAux( pos ); + clearSelection( true ); +} + + +void RegExpEditorWindow::cutCopyAux( QPoint pos ) +{ + if ( !hasSelection() ) { + RegExpWidget* widget = _top->widgetUnderPoint( pos, true ); + if ( !widget ) { + KMessageBox::information(this, i18n("There is no widget under cursor."), i18n("Invalid Operation") ); + return; + } + else { + widget->updateSelection( true ); // HACK! + } + } + + RegExp* regexp = _top->selection(); + RegExpWidgetDrag *clipboardData = new RegExpWidgetDrag( regexp, this ); + delete regexp; + + QClipboard* clipboard = qApp->clipboard(); + clipboard->setData( clipboardData ); + emit anythingOnClipboard( true ); + emit canSave( _top->hasAnyChildren() ); +} + + +void RegExpEditorWindow::slotStartPasteAction() +{ + QByteArray data = qApp->clipboard()->data()->encodedData( "KRegExpEditor/widgetdrag" ); + QTextStream stream( data, IO_ReadOnly ); + QString str = stream.read(); + + RegExp* regexp = WidgetFactory::createRegExp( str ); + if ( regexp ) + slotInsertRegExp( regexp ); +} + +void RegExpEditorWindow::slotEndActions() { + emit doneEditing(); + emit change(); + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::showRMBMenu( bool enableCutCopy ) +{ + enum CHOICES { CUT, COPY, PASTE, SAVE, EDIT }; + + if ( !_menu ) { + _menu = new QPopupMenu( 0 ); + _menu->insertItem(getIcon(QString::fromLocal8Bit("editcut")), + i18n("C&ut"), CUT); + _menu->insertItem(getIcon(QString::fromLocal8Bit("editcopy")), + i18n("&Copy"), COPY); + _menu->insertItem(getIcon(QString::fromLocal8Bit("editpaste")), + i18n("&Paste"), PASTE); + _menu->insertSeparator(); + _menu->insertItem(getIcon(QString::fromLocal8Bit("edit")), + i18n("&Edit"), EDIT); + _menu->insertItem(getIcon(QString::fromLocal8Bit("filesave")), + i18n("&Save Regular Expression..."), SAVE); + } + + _menu->setItemEnabled( CUT, enableCutCopy ); + _menu->setItemEnabled( COPY, enableCutCopy ); + + if ( ! qApp->clipboard()->data()->provides( "KRegExpEditor/widgetdrag" ) ) + _menu->setItemEnabled( PASTE, false ); + else + _menu->setItemEnabled( PASTE, true ); + + _menu->setItemEnabled( SAVE, _top->hasAnyChildren() ); + + RegExpWidget* editWidget = _top->findWidgetToEdit( QCursor::pos() ); + + _menu->setItemEnabled( EDIT, editWidget ); + + QPoint pos = QCursor::pos(); + int choice = _menu->exec( pos ); + switch ( choice ) { + case COPY: copy( pos ); break; + case CUT: cut( pos ); break; + case PASTE: slotStartPasteAction(); break; + case SAVE: slotSave(); break; + case EDIT: editWidget->edit(); break; + } + emit change(); + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::applyRegExpToSelection( RegExpType tp ) +{ + _top->applyRegExpToSelection( tp ); +} + +void RegExpEditorWindow::slotSave() +{ + QString dir = WidgetWinItem::path(); + QString txt; + +#ifdef QT_ONLY + txt = QInputDialog::getText( tr("Name for regexp"), tr("Enter name:") ); + if ( txt.isNull() ) + return; +#else + KLineEditDlg dlg(i18n("Enter name:"), QString::null, this); + dlg.setCaption(i18n("Name for Regular Expression")); + if (!dlg.exec()) return; + txt = dlg.text(); +#endif + + QString fileName = dir + QString::fromLocal8Bit("/") + txt + QString::fromLocal8Bit(".regexp"); + QFileInfo finfo( fileName ); + if ( finfo.exists() ) { + int answer = KMessageBox::warningContinueCancel( this, i18n("<p>Overwrite named regular expression <b>%1</b></p>").arg(txt), QString::null, i18n("Overwrite")); + if ( answer != KMessageBox::Continue ) + return; + } + + QFile file( fileName ); + if ( ! file.open(IO_WriteOnly) ) { + KMessageBox::sorry( this, i18n("Could not open file for writing: %1").arg(fileName) ); + return; + } + + // Convert to XML. + RegExp* regexp = _top->regExp(); + QString xml = regexp->toXmlString(); + delete regexp; + + QTextStream stream(&file); + stream << xml; + + file.close(); + emit savedRegexp(); +} + + +void RegExpEditorWindow::slotSetRegExp( RegExp* regexp ) +{ + // I have no clue why the following line is necesarry, but if it is not here + // then the editor area is messed up when calling slotSetRegExp before starting the eventloop. + qApp->processEvents(); + + delete _top; + RegExpWidget* widget = WidgetFactory::createWidget( regexp, this, this ); + if ( ! (_top = dynamic_cast<ConcWidget*>( widget ) ) ) { + // It was not a ConcWidget + _top = new ConcWidget( this, widget, this ); + } + _top->setToplevel(); + + _top->show(); + _layout->addWidget( _top ); + clearSelection( true ); // HACK? + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::updateCursorUnderPoint() +{ + RegExpWidget* widget = _top->widgetUnderPoint( QCursor::pos(), false ); + if ( widget ) + widget->updateCursorShape(); +} + +void RegExpEditorWindow::emitVerifyRegExp() +{ + emit verifyRegExp(); +} + + +QIconSet RegExpEditorWindow::getIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( name ) ); + return pix; +#else + return SmallIconSet( name ); +#endif +} + diff --git a/kregexpeditor/editorwindow.h b/kregexpeditor/editorwindow.h new file mode 100644 index 0000000..e925c59 --- /dev/null +++ b/kregexpeditor/editorwindow.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef editorwindow_h +#define editorwindow_h + +#include "drag.h" +#include "widgetfactory.h" +#include <qmultilineedit.h> +#include <qlabel.h> +#include <qiconset.h> +class RegExp; +class RegExpWidget; +class QHBoxLayout; + +/** Widget representing the editor window of a regular expression editor. + + @internal + This widget represent the editor part (That is the location where the + regexp widgets are located). + + Furthermore, it also responsible for: + @li Widget traversal operations (see e.g. @ref hasSelection, @ref + clearSelection, and @ref applyRegExpToSelection ). + @li Containing global information for regexp editing. (See @ref + _pasteData and @ref _insertInAction ) + + All subclasses of @ref RegExpWidget contains a pointer to the @ref + RegExpEditorWindow which the widget is a child of. They use this + pointer to start operations like rubber band selection, cut/paste etc. +*/ +class RegExpEditorWindow :public QWidget +{ + Q_OBJECT + +public: + RegExpEditorWindow(QWidget *parent, const char *name = 0); + + /** + Returns an object which represent the regular expression "drawn" in + the editor window. This object is capable of generating a textual + representation of the regexp (see @ref RegExp::emacs, and @ref + RegExp::perl etc) + */ + RegExp* regExp() const; + + /** + This method returns true if the rectangle starting at `globalPos' with + size `size' overlaps the rubber-band rectangle. + Note this method is only valid while doing rubber-band + selection. Afterwards, use @ref pointSelected instead. + */ + bool selectionOverlap( QPoint globalPos, QSize size ) const; + + /** + returns true if `pos' lays on top of a widget that is selected. + */ + bool pointSelected( QPoint pos ) const; + + /** + returns true if the editor has a selection. + */ + bool hasSelection() const; + + /** + clears the selection, and if `update', invokes update on all the + widgets + */ + void clearSelection( bool update ); + + /** + invoked update on the top widget, and ensures that `focusChild' is + visible. It's valid for `focusChild' to be 0. + */ + void updateContent(QWidget* focusChild); + + RegExp* pasteData() { return _pasteData; } + bool isPasteing() const { return _pasteInAction; } + bool isInserting() const { return _insertInAction; } + + /** + Returns the type currently being inserted. + This is the type, which was given to @ref slotInsertRegExp + */ + RegExpType insertType() const { return _insertTp; } + + /** + Create a regexp widget, so that it wraps around the current selected + regexp. + */ + void applyRegExpToSelection( RegExpType tp ); + + /** + Pops up the RMB menu, which contains cut, copy, past, ... + */ + void showRMBMenu( bool enableCutCopy ); + + virtual QSize sizeHint() const; + +public slots: + + /** + Set the editor window to the regular expression given as argument + */ + void slotSetRegExp( RegExp* regexp ); + + /** + Change editing mode to insertion. This means that the cursor will + change to a cross (where ever inserting of the `type' is allowed), + and the next mouse press in allowed places will result in that a + regular expression of type `type' will be inserted there. + + Note this method do not do the actual insertion. + + This method is used when the user presses one of the buttons to the + right of the editor window. + */ + void slotInsertRegExp( RegExpType type ); + + /** + Change editing state to selection. + */ + void slotDoSelect(); + + /** + Like @ref slotInsertRegExp above. This time, however, data will be + submitted in as a RegExp pointer. + + Note this method do not do the actual insertion. + + This method is called when the user pastes data (using the RPM menu), + or when a regular expression is loaded from file. + */ + void slotInsertRegExp( RegExp* regexp ); + + /** + see @ref RegExpWidget::deleteSelection + */ + void slotDeleteSelection(); + + /** + This method is invoked when the user selects paste in the RMB menu. It + will change the mouse cursor etc. as described in @ref + slotInsertRegExp + */ + void slotStartPasteAction(); + + /** + Ends an insert or paste action. This involves changing cursor back to + normal cursor. + */ + void slotEndActions(); + + void emitChange() { emit change(); } + + void updateCursorUnderPoint(); + + void slotCut(); + void slotCopy(); + void slotSave(); + +signals: + /** + This signal is emitted whenever the content of the editor window is + changed. + + If focusPoint is non-null then this point should be made visible + */ + void contentChanged( QPoint focusPoint ); + + /** + This signal is emitted whenever mouse is being dragged in the editor + window. `focusPoint' is the mouse' current position. + */ + void scrolling( QPoint focusPoint ); + + /** + see @ref RegExpScrolledEditorWindow::doneEditing + */ + void doneEditing(); + + /** + see @ref RegExpScrolledEditorWindow::change + */ + void change(); + + /** + see @ref RegExpScrolledEditorWindow::savedRegexp + */ + void savedRegexp(); + + /** + see @ref RegExpScrolledEditorWindow::verifyRegExp + */ + void verifyRegExp(); + + void anythingSelected( bool ); + void anythingOnClipboard( bool ); + void canSave( bool ); + + +protected: + virtual void mousePressEvent ( QMouseEvent* event ); + virtual void mouseMoveEvent ( QMouseEvent* event ); + virtual void mouseReleaseEvent( QMouseEvent *event); + virtual void paintEvent( QPaintEvent* event ); + +protected slots: + virtual void emitVerifyRegExp(); + +private: + void cutCopyAux( QPoint pos ); + void copy( QPoint pos ); + void cut( QPoint pos ); + +private: + /** This points to the top @ref RegExpWidget in the editor window. */ + ConcWidget *_top; + + /** This points to the layout manager for the editor window */ + QHBoxLayout* _layout; + + /** Start point and last point draw. Used when doing rubber band selection */ + QPoint _start, _lastPoint; + + /** The area which the rubber band selection is over */ + QRect _selection; + + /** + True when a rubber band selection rectangle is drawn, and need to be + un-drawn before next rubber band selection rectangle may be drawn. + */ + bool _undrawSelection; + + /** true when a paste action is in action (see @ref isPasteing ). */ + bool _pasteInAction; + + /** true when an insert action is in action (see @ref isInserting ). */ + bool _insertInAction; + + /** The type being inserted (see @ref insertType ) */ + RegExpType _insertTp; + + /** The data being inserted (see @ref pasteData ) */ + RegExp* _pasteData; + + /** Popup menu used for RMB */ + QPopupMenu* _menu; + + QIconSet getIcon( const QString& name ); + + bool _isDndOperation; +}; + +#endif // editorwindow_h diff --git a/kregexpeditor/emacsregexpconverter.cpp b/kregexpeditor/emacsregexpconverter.cpp new file mode 100644 index 0000000..327d04c --- /dev/null +++ b/kregexpeditor/emacsregexpconverter.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "emacsregexpconverter.h" +#include "regexp.h" +#include "altnregexp.h" +#include "concregexp.h" +#include "lookaheadregexp.h" +#include "textrangeregexp.h" +#include "textregexp.h" +#include "compoundregexp.h" +#include "dotregexp.h" +#include "positionregexp.h" +#include "repeatregexp.h" + +#include <kmessagebox.h> +#include <klocale.h> +bool EmacsRegExpConverter::canParse() +{ + return false; +} + +QString EmacsRegExpConverter::toString( AltnRegExp* regexp, bool markSelection ) +{ + QString res; + + bool first = true; + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + if ( !first ) { + res += QString::fromLatin1("\\|"); + } + first = false; + res += toStr( *it, markSelection ); + } + return res; + +} + +QString EmacsRegExpConverter::toString( ConcRegExp* regexp, bool markSelection ) +{ + QString res; + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + QString startPar = QString::fromLocal8Bit(""); + QString endPar = QString::fromLocal8Bit(""); + if ( (*it)->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "\\(" ); + endPar = QString::fromLatin1( "\\)" ); + } + + res += startPar + toStr( *it, markSelection ) + endPar; + } + + return res; + +} + +QString EmacsRegExpConverter::toString( LookAheadRegExp* /*regexp*/, bool /*markSelection*/ ) +{ + static bool haveWarned = false; + if ( ! haveWarned ) { + KMessageBox::sorry( 0, i18n("Look ahead regular expressions not supported in Emacs style") ); + haveWarned = true; + } + + return QString::null; +} + +QString EmacsRegExpConverter::toString( TextRangeRegExp* regexp, bool /*markSelection*/ ) +{ + QString txt; + + bool foundCarrot = false; + bool foundDash = false; + bool foundParenthesis = false; + + // print the single characters, but keep "^" as the very + // last element of the characters. + QStringList chars = regexp->chars(); + for (unsigned int i = 0; i< chars.count(); i++) { + if ( *chars.at(i) == QChar(']') ) { + foundParenthesis = true; + } + else if ( *chars.at(i) == QChar('-') ) { + foundDash = true; + } + else if ( *chars.at(i) == QChar('^') ) { + foundCarrot = true; + } + else { + txt.append( *chars.at(i) ); + } + } + + // Now insert the ranges. + QPtrList<StringPair> ranges = regexp->range(); + for ( QPtrListIterator<StringPair> it(ranges); *it; ++it ) { + txt.append((*it)->first()+ QString::fromLatin1("-")+ (*it)->second()); + } + + // Ok, its time to build each part of the regexp, here comes the rule: + // if a ']' is one of the characters, then it must be the first one in the + // list (after then opening '[' and eventually negation '^') + // Next if a '-' is one of the characters, then it must come + // finally if '^' is one of the characters, then it must not be the first + // one! + + QString res = QString::fromLatin1("["); + + if ( regexp->negate() ) + res.append(QString::fromLatin1("^")); + + + // a ']' must be the first character in teh range. + if ( foundParenthesis ) { + res.append(QString::fromLatin1("]")); + } + + // a '-' must be the first character ( only coming after a ']') + if ( foundDash ) { + res.append(QString::fromLatin1("-")); + } + + res += txt; + + // Insert equivalents to \s,\S,\d,\D,\w, and \W + // non-digit, non-space, and non-word is not supported in Emacs style + if ( regexp->digit() ) + res += QString::fromLocal8Bit("0-9"); + if ( regexp->space() ) + res += QString::fromLocal8Bit(" ") + QString( QChar( (char) 9 ) ); // Tab char + if ( regexp->wordChar() ) + res += QString::fromLocal8Bit("a-zA-Z"); + + if ( foundCarrot ) { + res.append( QChar( '^' ) ); + } + + res.append(QString::fromLatin1("]")); + + return res; +} + +QString EmacsRegExpConverter::toString( CompoundRegExp* regexp, bool markSelection ) +{ + return toStr( regexp->child(), markSelection ); +} + +QString EmacsRegExpConverter::toString( DotRegExp* /*regexp*/, bool /*markSelection*/ ) +{ + return QString::fromLatin1( "." ); +} + +QString EmacsRegExpConverter::toString( PositionRegExp* regexp, bool /*markSelection*/ ) +{ + static bool haveWarned = false; + switch ( regexp->position()) { + case PositionRegExp::BEGLINE: + return QString::fromLatin1("^"); + case PositionRegExp::ENDLINE: + return QString::fromLatin1("$"); + case PositionRegExp::WORDBOUNDARY: + case PositionRegExp::NONWORDBOUNDARY: + if ( ! haveWarned ) { + KMessageBox::sorry( 0, i18n( "Word boundary and non word boundary is not supported in Emacs syntax" ) ); + haveWarned = true; + return QString::fromLatin1(""); + } + } + return QString::fromLatin1(""); +} + +QString EmacsRegExpConverter::toString( RepeatRegExp* regexp, bool markSelection ) +{ + RegExp* child = regexp->child(); + QString cText = toStr( child, markSelection ); + QString startPar; + QString endPar; + + if ( child->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "\\(" ); + endPar = QString::fromLatin1( "\\)" ); + } + + if (regexp->min() == 0 && regexp->max() == -1) { + return startPar + cText +endPar + QString::fromLocal8Bit("*"); + } + else if ( regexp->min() == 0 && regexp->max() == 1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("?"); + } + else if ( regexp->min() == 1 && regexp->max() == -1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("+"); + } + else { + QString res = QString::fromLatin1(""); + for ( int i = 0; i < regexp->min(); ++i ) { + res += QString::fromLatin1( "\\(" ) + cText + QString::fromLatin1( "\\)" ); + } + if ( regexp->max() != -1 ) { + for ( int i = regexp->min(); i < regexp->max(); ++i ) { + res += QString::fromLatin1("\\(") + cText + QString::fromLatin1("\\)?"); + } + } + else + res += QString::fromLatin1("+"); + + return res; + } +} + +QString EmacsRegExpConverter::toString( TextRegExp* regexp, bool /*markSelection*/ ) +{ + QValueList<QChar> list; + list << QChar('$') + << QChar('^') + << QChar('.') + << QChar('*') + << QChar('+') + << QChar('?') + << QChar('[') + << QChar(']') + << QChar('\\'); + + QString res = escape( regexp->text(), list, QChar('\\') ); + return res; +} + +QString EmacsRegExpConverter::name() +{ + return QString::fromLatin1( "Emacs" ); +} + +int EmacsRegExpConverter::features() +{ + return WordStart | WordEnd; +} diff --git a/kregexpeditor/emacsregexpconverter.h b/kregexpeditor/emacsregexpconverter.h new file mode 100644 index 0000000..bbc9e94 --- /dev/null +++ b/kregexpeditor/emacsregexpconverter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef EMACSREGEXPCONVERTER_H +#define EMACSREGEXPCONVERTER_H + +#include "regexpconverter.h" + +class EmacsRegExpConverter :public RegExpConverter +{ +public: + virtual bool canParse(); + virtual QString name(); + virtual int features(); + virtual QString toString( AltnRegExp*, bool markSelection ); + virtual QString toString( ConcRegExp*, bool markSelection ); + virtual QString toString( LookAheadRegExp*, bool markSelection ); + virtual QString toString( TextRangeRegExp*, bool markSelection ); + virtual QString toString( CompoundRegExp*, bool markSelection ); + virtual QString toString( DotRegExp*, bool markSelection ); + virtual QString toString( PositionRegExp*, bool markSelection ); + virtual QString toString( RepeatRegExp*, bool markSelection ); + virtual QString toString( TextRegExp*, bool markSelection ); +}; + + +#endif /* EMACSREGEXPCONVERTER_H */ + diff --git a/kregexpeditor/errormap.cpp b/kregexpeditor/errormap.cpp new file mode 100644 index 0000000..c452ddb --- /dev/null +++ b/kregexpeditor/errormap.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <kmessagebox.h> + #include <klocale.h> +#endif + +#include "errormap.h" + +ErrorMap::ErrorMap() : _prevLineStartError( false ), _prevLineEndError( false ), _prevLookAHeadError( false ) +{ +} + +void ErrorMap::start() +{ + _lineStartError = false; + _lineEndError = false; + _lookAHeadError = false; +} + +void ErrorMap::end() +{ + _prevLineStartError = _lineStartError; + _prevLineEndError = _lineEndError; + _prevLookAHeadError = _lookAHeadError; +} + +void ErrorMap::lineStartError() +{ + if ( ! _prevLineStartError ) { + KMessageBox::information( 0, i18n("Your regular expression is invalid, due to something preceding a 'line start'."), + i18n("Regular Expression Error"), QString::fromLatin1("KRegExpEditorLineStartError") ); + } + _lineStartError = true; +} + +void ErrorMap::lineEndError() +{ + if ( !_prevLineEndError ) { + KMessageBox::information( 0, i18n("Your regular expression is invalid, due to something following a 'line end'."), + i18n("Regular Expression Error"), QString::fromLatin1("KRegExpEditorLineEndError") ); + } + _lineEndError = true; +} + + +void ErrorMap::lookAheadError() +{ + if ( !_prevLookAHeadError ) { + KMessageBox::information( 0, i18n("Your regular expression is invalid. 'Look Ahead' regular expression must be the last sub expression."), + i18n("Regular Expression Error"), QString::fromLatin1("KRegExpEditorLookAHeadError") ); + } + _lookAHeadError = true; +} + diff --git a/kregexpeditor/errormap.h b/kregexpeditor/errormap.h new file mode 100644 index 0000000..88034dd --- /dev/null +++ b/kregexpeditor/errormap.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef ERRORMAP_H +#define ERRORMAP_H + +class ErrorMap +{ +public: + ErrorMap(); + void start(); + void end(); + void lineStartError(); + void lineEndError(); + void lookAheadError(); +private: + bool _lineStartError, _prevLineStartError; + bool _lineEndError, _prevLineEndError; + bool _lookAHeadError, _prevLookAHeadError; +}; + +#endif diff --git a/kregexpeditor/extractrc-from-regexp b/kregexpeditor/extractrc-from-regexp new file mode 100755 index 0000000..70c30ad --- /dev/null +++ b/kregexpeditor/extractrc-from-regexp @@ -0,0 +1,85 @@ +#! /usr/bin/perl +# This file is a modified version of extractrc, with the only addition that it Title|Description in the textstring regexp. +# +# This script extracts messages from designer (.ui) and XMLGIU (.rc) files +# and writes on standard output (usually redirected to rc.cpp) +# the equivalent i18n() calls so that xgettext can parse them. + +$filename = ""; +@filenames = (); + +sub writeoutstring($) +{ + print STDOUT "i18n(\"@_[0]\"); // $filename \n"; +} + +while (defined ($ARGV[0])) +{ + $_ = shift; + $filename = $_; # maybe check for options + +if (! $filename) { + print STDERR "no file to open\n"; + exit 1; +} + +$string = ""; +$intext = 0; +$linenr = 0; +$inskippedprop = 0; + +open(FILE, $filename); + +READING: while ( <FILE> ) { + $linenr++; + if ($linenr == 1 && ($_ !~ /^<!DOCTYPE/) && ($_ !~ /^<\?xml/)) { + last READING; + } + + $string .= "\\n" . $_; + chomp($string); + + $textstring = '([tT][eE][xX][tT]|[tT]itle|[dD]escription|string|whatsthis|tooltip)>'; + + # The 'database' property contains strings that shouldn't be translated + if ($inskippedprop == 0 && ($string =~ /<property name=\"database\"/)) { + $inskippedprop = 1; + } elsif ($inskippedprop == 1 && ($string =~ /<\/property/)) { + $inskippedprop = 0; + $string = ""; + } + + if ($inskippedprop == 0 && $intext == 0) { + if ($string =~ /<$textstring/) { + $string =~ s/^.*<$textstring//; + $intext = 1; + $starting_linenr = $linenr; + } else { + $string = ""; + } + } + + if (($intext == 1) && ($string =~ /<\/$textstring/)) { + my $text = $string; + $text =~ s/<\/$textstring.*$//; + $text =~ s/</</g; + $text =~ s/>/>/g; + $text =~ s/&/&/g; + $text =~ s/\"/\\\"/g; + writeoutstring($text); + $string =~ s/^.*<\/$textstring//; + $intext = 0; + # Text can be multiline in .ui files (possibly), but we warn about it in XMLGUI .rc files. + if ($linenr != $starting_linenr && $filename =~ m/\.rc$/) { + print STDERR "there is <text> floating $filename\n"; + } + } + +} + +if ($intext == 1) { + print STDERR "parsing error in $filename $linenr\n"; + exit 1; +} + +} diff --git a/kregexpeditor/gen_qregexplexer.cpp b/kregexpeditor/gen_qregexplexer.cpp new file mode 100644 index 0000000..30f2284 --- /dev/null +++ b/kregexpeditor/gen_qregexplexer.cpp @@ -0,0 +1,1980 @@ +#define yy_create_buffer qregexp_create_buffer +#define yy_delete_buffer qregexp_delete_buffer +#define yy_scan_buffer qregexp_scan_buffer +#define yy_scan_string qregexp_scan_string +#define yy_scan_bytes qregexp_scan_bytes +#define yy_flex_debug qregexp_flex_debug +#define yy_init_buffer qregexp_init_buffer +#define yy_flush_buffer qregexp_flush_buffer +#define yy_load_buffer_state qregexp_load_buffer_state +#define yy_switch_to_buffer qregexp_switch_to_buffer +#define yyin qregexpin +#define yyleng qregexpleng +#define yylex qregexplex +#define yyout qregexpout +#define yyrestart qregexprestart +#define yytext qregexptext + +#line 19 "gen_qregexplexer.cpp" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 29 +#define YY_END_OF_BUFFER 30 +static yyconst short int yy_accept[53] = + { 0, + 0, 0, 30, 28, 29, 13, 18, 19, 21, 23, + 12, 22, 28, 28, 14, 28, 20, 0, 0, 25, + 0, 27, 27, 26, 2, 4, 6, 8, 9, 1, + 3, 5, 7, 27, 0, 0, 24, 17, 15, 16, + 25, 11, 26, 10, 0, 11, 10, 11, 10, 11, + 10, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 1, 4, 1, 1, 1, 5, + 6, 7, 8, 9, 1, 10, 1, 11, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 14, 1, 1, + 15, 1, 16, 1, 17, 18, 17, 19, 17, 17, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 20, 1, 1, 1, 21, 1, 1, 1, + 22, 23, 24, 25, 1, 1, 26, 27, 17, 28, + + 17, 26, 1, 1, 1, 1, 1, 1, 1, 29, + 1, 1, 1, 29, 30, 29, 1, 29, 31, 32, + 1, 1, 33, 34, 35, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[36] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[59] = + { 0, + 0, 33, 53, 137, 137, 137, 32, 137, 137, 137, + 137, 137, 2, 67, 137, 19, 137, 0, 20, 18, + 12, 137, 0, 6, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 0, 34, 94, 137, 137, 137, 137, + 137, 9, 39, 0, 97, 48, 0, 50, 0, 137, + 137, 137, 132, 134, 27, 22, 11, 7 + } ; + +static yyconst short int yy_def[59] = + { 0, + 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 54, 52, 52, 52, 52, 52, 54, 54, + 54, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 55, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 56, 52, 52, 57, 52, 58, 52, + 52, 0, 52, 52, 52, 52, 52, 52 + } ; + +static yyconst short int yy_nxt[173] = + { 0, + 52, 5, 38, 6, 7, 8, 9, 10, 51, 11, + 42, 42, 49, 39, 40, 12, 43, 43, 43, 46, + 46, 13, 14, 47, 15, 20, 21, 35, 44, 36, + 36, 36, 16, 17, 5, 20, 6, 7, 8, 9, + 10, 41, 11, 41, 45, 45, 45, 18, 12, 43, + 43, 43, 52, 37, 13, 14, 52, 15, 48, 48, + 50, 50, 52, 52, 52, 16, 17, 22, 37, 22, + 22, 22, 22, 22, 22, 22, 22, 23, 24, 24, + 22, 22, 22, 22, 25, 26, 27, 28, 22, 22, + 22, 22, 29, 30, 31, 29, 32, 33, 34, 22, + + 22, 22, 35, 52, 36, 36, 36, 45, 45, 45, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 37, 52, + 52, 37, 4, 4, 19, 19, 3, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52 + } ; + +static yyconst short int yy_chk[173] = + { 0, + 0, 1, 18, 1, 1, 1, 1, 1, 58, 1, + 23, 23, 57, 18, 18, 1, 24, 24, 24, 42, + 42, 1, 1, 56, 1, 13, 13, 16, 55, 16, + 16, 16, 1, 1, 2, 21, 2, 2, 2, 2, + 2, 20, 2, 19, 35, 35, 35, 7, 2, 43, + 43, 43, 3, 16, 2, 2, 0, 2, 46, 46, + 48, 48, 0, 0, 0, 2, 2, 14, 35, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + + 14, 14, 36, 0, 36, 36, 36, 45, 45, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, + 0, 45, 53, 53, 54, 54, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "qregexpparser.l" +#define INITIAL 0 +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#line 21 "qregexpparser.l" + #include <qstring.h> + #include "textrangeregexp.h" + #include "gen_qregexpparser.hh" +#ifdef QT_ONLY + #include "compat.h" +#endif + void parseRange( char* txt, int* min, int* max ); + RegExp* parseCharClass( char* match ); +#line 464 "gen_qregexplexer.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 38 "qregexpparser.l" + +#line 617 "gen_qregexplexer.cpp" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 137 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 39 "qregexpparser.l" +return TOK_PosWordChar; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 40 "qregexpparser.l" +return TOK_PosNonWordChar; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 41 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 47 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 53 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 59 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 65 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 71 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 77 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit( yytext ) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 84 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 90 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 96 "qregexpparser.l" +return TOK_Dot; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 97 "qregexpparser.l" +return TOK_Dollar; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 98 "qregexpparser.l" +return TOK_Carat; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 99 "qregexpparser.l" +return TOK_MagicLeftParent; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 100 "qregexpparser.l" +return TOK_PosLookAhead; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 101 "qregexpparser.l" +return TOK_NegLookAhead; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 102 "qregexpparser.l" +return TOK_LeftParen; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 103 "qregexpparser.l" +return TOK_RightParent; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 104 "qregexpparser.l" +return TOK_Bar; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 105 "qregexpparser.l" +{ qregexplval.range.min = 0; qregexplval.range.max=-1; return TOK_Quantifier; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 106 "qregexpparser.l" +{ qregexplval.range.min = 0; qregexplval.range.max=1; return TOK_Quantifier; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 107 "qregexpparser.l" +{ qregexplval.range.min = 1; qregexplval.range.max=-1; return TOK_Quantifier; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 108 "qregexpparser.l" +{ parseRange( yytext, &qregexplval.range.min, &qregexplval.range.max ); return TOK_Quantifier; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 109 "qregexpparser.l" +{ qregexplval.regexp = parseCharClass(yytext); return TOK_CharClass; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 110 "qregexpparser.l" +{ qregexplval.backRef = atoi( yytext+1 ); return TOK_BackRef; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 111 "qregexpparser.l" +{ qregexplval.ch = yytext[1]; return TOK_EscapeChar; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 112 "qregexpparser.l" +{ qregexplval.ch = yytext[0]; return TOK_Char; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 114 "qregexpparser.l" +ECHO; + YY_BREAK +#line 890 "gen_qregexplexer.cpp" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 52); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +#include<unistd.h> +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 114 "qregexpparser.l" + + +void setParseData( QString qstr ) { + const char* cstr; + if ( qstr.isNull() ) + cstr = ""; + else + cstr = qstr.latin1(); + yy_switch_to_buffer( yy_scan_string( cstr ) ); +} + +/** + This function parses a range in a form similar to "{3,4}", "{,7}" + etc. and returns the value in the integers pointed to by min and max. +*/ +void parseRange( char* txt, int* min, int* max ) +{ + + /* + case txt min max + 1 {} 0 -1 + 2 {,} 0 -1 + 3 {5} 5 5 + 4 {5,} 5 -1 + 5 {,7} 0 7 + 6 {5,7} 5 7 + */ + char c; + int i = 1; + int minimum=0, maximum=0; + int minFound=0, maxFound=0, commaFound = 0; + + while ( (c = txt[i++]) != ',' && c != '}') { + minimum = minimum*10+ c-'0'; + minFound=1; + } + + if ( c == ',' ) + commaFound = 1; + + if ( c != '}' ) { + while ( (c = txt[i++]) != '}') { + maximum = maximum*10+ c-'0'; + maxFound = 1; + } + } + + *min = minimum; + if ( maxFound ) + *max = maximum; /* case 5,6 */ + else if ( !minFound ) + *max = -1; /* case 1,2 */ + else if ( commaFound ) + *max = -1; /* case 4 */ + else + *max = minimum; /* case 3 */ +} + + +/** + This function parses a character range like "[^ab1-4]". +*/ +RegExp* parseCharClass( char* match ) +{ + TextRangeRegExp* res = new TextRangeRegExp( false ); + QString txt = QString::fromLocal8Bit( match ); + txt = txt.mid(1,txt.length()-2); + + unsigned int i = 0; + QChar ch = txt.at(i++); + QString pendingChar; + QString thisChar; + bool charPending = false; + bool rangePending = false; + bool flushPending = false; + + if ( ch == QChar('^') ) { + res->setNegate( true ); + ch = txt.at(i++); + } + + do { + // If a character is pending, and the next char is '-' then we are + // possible looking at a range. + if ( ch == QChar('-') && charPending ) { + rangePending = true; + ch = txt.at(i++); + continue; + } + + // If we have a pending character, but do not also have a pending + // range, then the pending character was not part of a range, and + // should therefore just be added as a single character. + if ( charPending && !rangePending ) { + res->addCharacter( pendingChar ); + charPending = false; + } + + if ( ch == QChar('\\') ) { + // Handle the cases where an escape character is specified. + ch = txt.at(i++); + + if ( ch == QChar('a') || ch == QChar('f') || ch == QChar('n') || ch == QChar('r') || ch == QChar('t') || ch == QChar('v') ) { + // These are just seen as normal characters. + thisChar = QString::fromLocal8Bit("\\") + ch; + } + else if ( ch == QChar('d') ) { + // The following characters represent character groups. If any of + // these are seen in a range, then the range is ignored, thus [a-\s] + // matches an 'a', a '-', and a space (\s means space). + res->setDigit( true ); + flushPending = true; + } + else if ( ch == QChar('D') ) { + res->setNonDigit( true ); + flushPending = true; + } + else if ( ch == QChar('s') ) { + res->setSpace( true ); + flushPending = true; + } + else if ( ch == QChar('S') ) { + res->setNonSpace( true ); + flushPending = true; + } + else if ( ch == QChar('w') ) { + res->setWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('W') ) { + res->setNonWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('x') || ch == QChar('X') ) { + // This is a hexidecimal character: \xHHHH + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == 'a' || ch == 'A' || ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'd' || ch == 'D' || + ch == 'e' || ch == 'E' || ch == 'f' || ch == 'F' || + ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || + ch == '8' || ch == '9' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str; + } + else if ( ch == QChar('0') ) { + // This is an octal character + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str ; + } + else { + // Anything else escaped just means the character itself. + thisChar = ch; + } + } + else { + // A non escaped character. + thisChar = ch; + } + + // The characters \s,\S,\w,\W,\d or \D, can not be part of a range, + // thus if they are meet in what looks like a range, then the + // characters of the range is justed seen as normal non range + // characters. thus [a-\s] matches an 'a', a '-', and a space (\s means + // space). + if ( flushPending ) { + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + flushPending = false; + charPending = false; + rangePending = false; + } + else { + if ( rangePending ) { + res->addRange( pendingChar, thisChar ); + charPending = false; + rangePending = false; + } + else { + pendingChar = thisChar; + charPending = true; + } + } + ch = txt.at(i++); + } + while ( ch != QChar(']') && i <= txt.length() ); + + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + + return res; +} diff --git a/kregexpeditor/gen_qregexpparser.cc b/kregexpeditor/gen_qregexpparser.cc new file mode 100644 index 0000000..b366293 --- /dev/null +++ b/kregexpeditor/gen_qregexpparser.cc @@ -0,0 +1,1447 @@ +/* A Bison parser, made from qregexpparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ +#define yyparse qregexpparse +#define yylex qregexplex +#define yyerror qregexperror +#define yylval qregexplval +#define yychar qregexpchar +#define yydebug qregexpdebug +#define yynerrs qregexpnerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_Dot = 258, + TOK_Dollar = 259, + TOK_Carat = 260, + TOK_MagicLeftParent = 261, + TOK_PosLookAhead = 262, + TOK_NegLookAhead = 263, + TOK_LeftParen = 264, + TOK_RightParent = 265, + TOK_Bar = 266, + TOK_Quantifier = 267, + TOK_BackRef = 268, + TOK_CharClass = 269, + TOK_Char = 270, + TOK_EscapeChar = 271, + TOK_PosWordChar = 272, + TOK_PosNonWordChar = 273 + }; +#endif +#define TOK_Dot 258 +#define TOK_Dollar 259 +#define TOK_Carat 260 +#define TOK_MagicLeftParent 261 +#define TOK_PosLookAhead 262 +#define TOK_NegLookAhead 263 +#define TOK_LeftParen 264 +#define TOK_RightParent 265 +#define TOK_Bar 266 +#define TOK_Quantifier 267 +#define TOK_BackRef 268 +#define TOK_CharClass 269 +#define TOK_Char 270 +#define TOK_EscapeChar 271 +#define TOK_PosWordChar 272 +#define TOK_PosNonWordChar 273 + + + + +/* Copy the first part of user declarations. */ +#line 18 "qregexpparser.y" + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kmessagebox.h> +#endif + + #include <qstring.h> + #include <stdlib.h> + + #include "regexp.h" + #include "textregexp.h" + #include "textrangeregexp.h" + #include "repeatregexp.h" + #include "lookaheadregexp.h" + #include "concregexp.h" + #include "altnregexp.h" + #include "positionregexp.h" + #include "dotregexp.h" + #include "compoundregexp.h" + + extern int yylex(); + extern void setParseData( QString str ); + int yyerror (const char *); + void setParseResult( RegExp* ); + RegExp* parseQtRegExp( QString qstr, bool* ok ); + static RegExp* parseResult; + static int _index; + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#ifndef YYSTYPE +#line 49 "qregexpparser.y" +typedef union { + struct { + int min; + int max; + } range; + int backRef; + RegExp* regexp; + char ch; +} yystype; +/* Line 193 of /usr/share/bison/yacc.c. */ +#line 159 "gen_qregexpparser.cc" +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#ifndef YYLTYPE +typedef struct yyltype +{ + int first_line; + int first_column; + int last_line; + int last_column; +} yyltype; +# define YYLTYPE yyltype +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +/* Copy the second part of user declarations. */ + + +/* Line 213 of /usr/share/bison/yacc.c. */ +#line 180 "gen_qregexpparser.cc" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 27 +#define YYLAST 47 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 19 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 8 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 27 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 36 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 273 + +#define YYTRANSLATE(X) \ + ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 4, 6, 8, 12, 14, 17, 20, + 22, 25, 27, 30, 32, 36, 40, 44, 48, 50, + 52, 54, 56, 58, 60, 62, 64, 66 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 21, 0, -1, -1, 22, -1, 20, -1, 22, 11, + 23, -1, 23, -1, 22, 11, -1, 11, 23, -1, + 11, -1, 23, 24, -1, 24, -1, 25, 12, -1, + 25, -1, 9, 22, 10, -1, 6, 22, 10, -1, + 7, 22, 10, -1, 8, 22, 10, -1, 14, -1, + 26, -1, 4, -1, 5, -1, 3, -1, 13, -1, + 17, -1, 18, -1, 15, -1, 16, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned char yyrline[] = +{ + 0, 80, 80, 82, 83, 86, 96, 97, 107, 112, + 115, 129, 136, 139, 142, 145, 146, 149, 152, 153, + 154, 155, 156, 157, 172, 173, 176, 182 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TOK_Dot", "TOK_Dollar", "TOK_Carat", + "TOK_MagicLeftParent", "TOK_PosLookAhead", "TOK_NegLookAhead", + "TOK_LeftParen", "TOK_RightParent", "TOK_Bar", "TOK_Quantifier", + "TOK_BackRef", "TOK_CharClass", "TOK_Char", "TOK_EscapeChar", + "TOK_PosWordChar", "TOK_PosNonWordChar", "$accept", "empty", "regexp", + "expression", "term", "factor", "atom", "char", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 19, 20, 21, 21, 22, 22, 22, 22, 22, + 23, 23, 24, 24, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 26, 26 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 0, 1, 1, 3, 1, 2, 2, 1, + 2, 1, 2, 1, 3, 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 2, 22, 20, 21, 0, 0, 0, 0, 9, 23, + 18, 26, 27, 24, 25, 4, 0, 3, 6, 11, + 13, 19, 0, 0, 0, 0, 8, 1, 7, 10, + 12, 15, 16, 17, 14, 5 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 15, 16, 17, 18, 19, 20, 21 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -18 +static const yysigned_char yypact[] = +{ + -1, -18, -18, -18, -1, -1, -1, -1, 18, -18, + -18, -18, -18, -18, -18, -18, 11, 8, 18, -18, + 16, -18, 19, 31, 34, 36, 18, -18, 18, -18, + -18, -18, -18, -18, -18, 18 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -18, -18, -18, 33, -8, -17, -18, -18 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, parse error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 26, 29, 1, 2, 3, 4, 5, 6, 7, 29, + 8, 27, 9, 10, 11, 12, 13, 14, 29, 28, + 35, 1, 2, 3, 4, 5, 6, 7, 30, 31, + 28, 9, 10, 11, 12, 13, 14, 22, 23, 24, + 25, 32, 28, 0, 33, 28, 34, 28 +}; + +static const yysigned_char yycheck[] = +{ + 8, 18, 3, 4, 5, 6, 7, 8, 9, 26, + 11, 0, 13, 14, 15, 16, 17, 18, 35, 11, + 28, 3, 4, 5, 6, 7, 8, 9, 12, 10, + 11, 13, 14, 15, 16, 17, 18, 4, 5, 6, + 7, 10, 11, -1, 10, 11, 10, 11 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 3, 4, 5, 6, 7, 8, 9, 11, 13, + 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, + 25, 26, 22, 22, 22, 22, 23, 0, 11, 24, + 12, 10, 10, 10, 10, 23 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#define YYLEX yylex () + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*-----------------------------. +| Print this symbol on YYOUT. | +`-----------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue) +#else +yysymprint (yyout, yytype, yyvalue) + FILE* yyout; + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyout, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyout, yytoknum[yytype], yyvalue); +# endif + } + else + YYFPRINTF (yyout, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyout, ")"); +} +#endif /* YYDEBUG. */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yydestruct (int yytype, YYSTYPE yyvalue) +#else +yydestruct (yytype, yyvalue) + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + switch (yytype) + { + default: + break; + } +} + + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of parse errors so far. */ +int yynerrs; + + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with. */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more. */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + YYDPRINTF ((stderr, "Next token is ")); + YYDSYMPRINT ((stderr, yychar1, yylval)); + YYDPRINTF ((stderr, "\n")); + } + + /* If the proper action on seeing token YYCHAR1 is to reduce or to + detect an error, take that action. */ + yyn += yychar1; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn - 1, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + switch (yyn) + { + case 3: +#line 82 "qregexpparser.y" + { setParseResult( yyvsp[0].regexp) ; } + break; + + case 4: +#line 83 "qregexpparser.y" + { setParseResult( new ConcRegExp( false ) ); } + break; + + case 5: +#line 86 "qregexpparser.y" + { + if ( dynamic_cast<AltnRegExp*>( yyvsp[-2].regexp ) ) { + yyval.regexp = yyvsp[-2].regexp; + } + else { + yyval.regexp = new AltnRegExp( false ); + dynamic_cast<AltnRegExp*>( yyval.regexp )->addRegExp( yyvsp[-2].regexp ); + } + dynamic_cast<AltnRegExp*>( yyval.regexp )->addRegExp( yyvsp[0].regexp ); + } + break; + + case 6: +#line 96 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 7: +#line 97 "qregexpparser.y" + { + if ( dynamic_cast<AltnRegExp*>( yyvsp[-1].regexp ) ) { + yyval.regexp = yyvsp[-1].regexp; + } + else { + yyval.regexp = new AltnRegExp( false ); + dynamic_cast<AltnRegExp*>( yyval.regexp )->addRegExp( yyvsp[-1].regexp ); + } + dynamic_cast<AltnRegExp*>( yyval.regexp )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + } + break; + + case 8: +#line 107 "qregexpparser.y" + { + yyval.regexp = new AltnRegExp( false ); + dynamic_cast<AltnRegExp*>( yyval.regexp )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + dynamic_cast<AltnRegExp*>( yyval.regexp )->addRegExp( yyvsp[0].regexp ); + } + break; + + case 9: +#line 112 "qregexpparser.y" + { yyval.regexp = new AltnRegExp( false ); } + break; + + case 10: +#line 115 "qregexpparser.y" + { + RegExp* last = dynamic_cast<ConcRegExp*>( yyvsp[-1].regexp )->lastRegExp(); + TextRegExp *reg1, *reg2; + + if ( last && ( reg1 = dynamic_cast<TextRegExp*>( last ) ) && + ( reg2 = dynamic_cast<TextRegExp*>( yyvsp[0].regexp ) ) ) { + reg1->append( reg2->text() ); + delete reg2; + } + else { + dynamic_cast<ConcRegExp*>(yyval.regexp)->addRegExp( yyvsp[0].regexp ); + } + yyval.regexp = yyvsp[-1].regexp; + } + break; + + case 11: +#line 129 "qregexpparser.y" + { + ConcRegExp* reg = new ConcRegExp( false ); + reg->addRegExp( yyvsp[0].regexp ); + yyval.regexp = reg; + } + break; + + case 12: +#line 136 "qregexpparser.y" + { + yyval.regexp = new RepeatRegExp( false, yyvsp[0].range.min, yyvsp[0].range.max, yyvsp[-1].regexp ); + } + break; + + case 13: +#line 139 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 14: +#line 142 "qregexpparser.y" + { + yyval.regexp = yyvsp[-1].regexp; + } + break; + + case 15: +#line 145 "qregexpparser.y" + { yyval.regexp = yyvsp[-1].regexp; } + break; + + case 16: +#line 146 "qregexpparser.y" + { + yyval.regexp = new LookAheadRegExp( false, LookAheadRegExp::POSITIVE, yyvsp[-1].regexp ); + } + break; + + case 17: +#line 149 "qregexpparser.y" + { + yyval.regexp = new LookAheadRegExp( false, LookAheadRegExp::NEGATIVE, yyvsp[-1].regexp ); + } + break; + + case 18: +#line 152 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 19: +#line 153 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 20: +#line 154 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::ENDLINE ); } + break; + + case 21: +#line 155 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::BEGLINE ); } + break; + + case 22: +#line 156 "qregexpparser.y" + { yyval.regexp = new DotRegExp( false ); } + break; + + case 23: +#line 157 "qregexpparser.y" + { + QString match = QString::fromLocal8Bit("\\%1").arg( yyvsp[0].backRef ); + yyval.regexp = new TextRegExp( false, match ); + KMessageBox::information(0,i18n("<qt>Back reference regular expressions are not supported.<p>" + "<tt>\\1</tt>, <tt>\\2</tt>, ... are <i>back references</i>, meaning they refer to " + "previous matches. " + "Unfortunately this is not supported in the current version of this editor.<p>" + "In the graphical area the text <b>%1</b> has been inserted. This is however " + "just a workaround to ensure that the application handles the regexp at all. " + "Therefore, as soon as you edit the regular expression in the graphical area, " + "the back reference will be replaced by matching the text <b>%2</b> literally.") + .arg( match ).arg( match ), + i18n("Back reference regular expressions not supported"), + QString::fromLocal8Bit("backReferenceNotSupported") ); + } + break; + + case 24: +#line 172 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::WORDBOUNDARY ); } + break; + + case 25: +#line 173 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::NONWORDBOUNDARY ); } + break; + + case 26: +#line 176 "qregexpparser.y" + { + if ( yyvsp[0].ch == '{' || yyvsp[0].ch == '}' || yyvsp[0].ch == '[' || yyvsp[0].ch == ']' || yyvsp[0].ch == '\\' ) { + yyerror( "illigal character - needs escaping" ); + } + yyval.regexp = new TextRegExp( false, QString::fromLocal8Bit("%1").arg(yyvsp[0].ch)); + } + break; + + case 27: +#line 182 "qregexpparser.y" + { yyval.regexp = new TextRegExp( false, QString::fromLocal8Bit("%1").arg(yyvsp[0].ch)); } + break; + + + } + +/* Line 1016 of /usr/share/bison/yacc.c. */ +#line 1209 "gen_qregexpparser.cc" + + yyvsp -= yylen; + yyssp -= yylen; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyssp > yyss) + { + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], + *yyvsp)); + YYDPRINTF ((stderr, "\n")); + yydestruct (yystos[*yyssp], *yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yydestruct (yychar1, yylval); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], *yyvsp)); + YYDPRINTF ((stderr, "\n")); + + yydestruct (yystos[yystate], *yyvsp); + yyvsp--; + yystate = *--yyssp; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 185 "qregexpparser.y" + + +RegExp* parseQtRegExp( QString qstr, bool* ok ) { + _index = 0; + parseResult = 0; + setParseData( qstr ); + yyparse(); + *ok = ( yynerrs == 0 ); + return parseResult; +} + +void setParseResult( RegExp* regexp ) { + parseResult = regexp; +} + +int yyerror(const char *) { + yynerrs++; + return 0; +} + diff --git a/kregexpeditor/gen_qregexpparser.hh b/kregexpeditor/gen_qregexpparser.hh new file mode 100644 index 0000000..19b2558 --- /dev/null +++ b/kregexpeditor/gen_qregexpparser.hh @@ -0,0 +1,93 @@ +/* A Bison parser, made from qregexpparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef BISON_GEN_QREGEXPPARSER_HH +# define BISON_GEN_QREGEXPPARSER_HH + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_Dot = 258, + TOK_Dollar = 259, + TOK_Carat = 260, + TOK_MagicLeftParent = 261, + TOK_PosLookAhead = 262, + TOK_NegLookAhead = 263, + TOK_LeftParen = 264, + TOK_RightParent = 265, + TOK_Bar = 266, + TOK_Quantifier = 267, + TOK_BackRef = 268, + TOK_CharClass = 269, + TOK_Char = 270, + TOK_EscapeChar = 271, + TOK_PosWordChar = 272, + TOK_PosNonWordChar = 273 + }; +#endif +#define TOK_Dot 258 +#define TOK_Dollar 259 +#define TOK_Carat 260 +#define TOK_MagicLeftParent 261 +#define TOK_PosLookAhead 262 +#define TOK_NegLookAhead 263 +#define TOK_LeftParen 264 +#define TOK_RightParent 265 +#define TOK_Bar 266 +#define TOK_Quantifier 267 +#define TOK_BackRef 268 +#define TOK_CharClass 269 +#define TOK_Char 270 +#define TOK_EscapeChar 271 +#define TOK_PosWordChar 272 +#define TOK_PosNonWordChar 273 + + + + +#ifndef YYSTYPE +#line 49 "qregexpparser.y" +typedef union { + struct { + int min; + int max; + } range; + int backRef; + RegExp* regexp; + char ch; +} yystype; +/* Line 1281 of /usr/share/bison/yacc.c. */ +#line 86 "gen_qregexpparser.hh" +# define YYSTYPE yystype +#endif + +extern YYSTYPE qregexplval; + + +#endif /* not BISON_GEN_QREGEXPPARSER_HH */ + diff --git a/kregexpeditor/hi128-app-kregexpeditor.png b/kregexpeditor/hi128-app-kregexpeditor.png Binary files differnew file mode 100644 index 0000000..e1ea769 --- /dev/null +++ b/kregexpeditor/hi128-app-kregexpeditor.png diff --git a/kregexpeditor/hi16-app-kregexpeditor.png b/kregexpeditor/hi16-app-kregexpeditor.png Binary files differnew file mode 100644 index 0000000..86f7882 --- /dev/null +++ b/kregexpeditor/hi16-app-kregexpeditor.png diff --git a/kregexpeditor/hi22-app-kregexpeditor.png b/kregexpeditor/hi22-app-kregexpeditor.png Binary files differnew file mode 100644 index 0000000..11a7991 --- /dev/null +++ b/kregexpeditor/hi22-app-kregexpeditor.png diff --git a/kregexpeditor/hi32-app-kregexpeditor.png b/kregexpeditor/hi32-app-kregexpeditor.png Binary files differnew file mode 100644 index 0000000..af0f3f7 --- /dev/null +++ b/kregexpeditor/hi32-app-kregexpeditor.png diff --git a/kregexpeditor/hi48-app-kregexpeditor.png b/kregexpeditor/hi48-app-kregexpeditor.png Binary files differnew file mode 100644 index 0000000..fc589c9 --- /dev/null +++ b/kregexpeditor/hi48-app-kregexpeditor.png diff --git a/kregexpeditor/hi64-app-kregexpeditor.png b/kregexpeditor/hi64-app-kregexpeditor.png Binary files differnew file mode 100644 index 0000000..81013f9 --- /dev/null +++ b/kregexpeditor/hi64-app-kregexpeditor.png diff --git a/kregexpeditor/infopage.cpp b/kregexpeditor/infopage.cpp new file mode 100644 index 0000000..8f373c5 --- /dev/null +++ b/kregexpeditor/infopage.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kapplication.h> +#endif + +#include "infopage.h" + +InfoPage::InfoPage( QWidget* parent, const char* name ) + :KTextBrowser( parent, name ) +{ + QString txt = + QString::fromLatin1( "<qt>" ) + + i18n( "Translators, feel free to add yourself in the text below, asking for a postcard ;-), " + "also feel free to add a section saying <h2>Translators</h2>. " + "Kind regards, and thanks for your work - Jesper.", + "<h1>Regular Expression Editor</h1>" + "<p>What you are currently looking at is an editor for <i>Regular Expressions</i>.</p>" + "<p>The upper part in the middle is the editing area, the lower part is a verification window where you can " + "try your regular expressions right away. The row of buttons is the editing actions. " + "This is actually very similar to common drawing programs. Select an editing tool to start " + "editing your regular expression, and press the mouse button in the editing area where you want " + "this item inserted.</p>" + "<p>For a more detailed description of this editor see the <a href=\"doc://\">info pages</a></p>" + + "<h2>What is a regular expression?</h2>" + "If you do not know what a regular expression is, then it might be a good idea " + "to read <a href=\"doc://whatIsARegExp\">the introduction to regular expressions</a>.<p>"); + +#ifdef HOUSEOFFUSION + txt += tr("<h2>House Of Fusion note</h2>" + "If you want to donate money to continue development on the KRegExpEditor port for " + "house of fusion then please contact Michael Dinowitz (mdinowit@houseoffusion.com)."); +#endif + txt += i18n( "<h2>Send the author an electronic postcard</h2>" + "I don't get any money for working on KRegExpEditor, " + "I therefore appreciate it very much when users tell me what they think about my work. " + "I would therefore be very happy if you <a href=\"mailto:blackie@kde.org?subject=KRegExpEditor\">" + "sent me a short mail</a>, telling me that you use my regular expression editor." + + "<h2>Author</h2>" + "<a href=\"http://www.blackie.dk/\">Jesper K. Pedersen</a> <<a href=\"mailto:blackie@kde.org\">blackie@kde.org</a>>") + + QString::fromLatin1( "</qt>" ); + setText( txt ); +} + +void InfoPage::setSource ( const QString& name ) +{ +#ifdef QT_ONLY + mimeSourceFactory()->setFilePath( QStringList() << QString::fromLatin1("manual/")); + QString nm = name; + if ( nm.endsWith("/") ) + nm = nm.left( nm.length()-1); + + if ( nm.startsWith("mailto:") ) { + QMessageBox::information( this, tr("Support mail"), tr("Please send the mail to blackie@kde.org") ); + return; + } + if ( nm.startsWith( "http:" ) ) + return; + + + if ( nm == "doc://" ) + nm = "doc://index"; + + if ( nm.startsWith( QString::fromLocal8Bit("doc://") ) ) { + nm = nm.mid(6) + ".html"; + } + + QTextBrowser::setSource( nm ); +#else + if ( name.startsWith( QString::fromLocal8Bit("doc://") ) ) { + kapp->invokeHelp( name.mid(6, name.length()-7), QString::fromLocal8Bit("KRegExpEditor") ); + } + else { + KTextBrowser::setSource( name ); // handle mailto and other links + } +#endif +} diff --git a/kregexpeditor/infopage.h b/kregexpeditor/infopage.h new file mode 100644 index 0000000..b518979 --- /dev/null +++ b/kregexpeditor/infopage.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef infopage_h +#define infopage_h + +#ifdef QT_ONLY + #include "compat.h" + #include <qtextbrowser.h> +#else + # include <ktextbrowser.h> +#endif + +class InfoPage :public KTextBrowser +{ +public: + InfoPage( QWidget* parent, const char* name ); + virtual void setSource ( const QString& name ); +}; + + + +#endif diff --git a/kregexpeditor/kregexpeditor.desktop b/kregexpeditor/kregexpeditor.desktop new file mode 100644 index 0000000..ebffee5 --- /dev/null +++ b/kregexpeditor/kregexpeditor.desktop @@ -0,0 +1,76 @@ +[Desktop Entry] +Name=KRegExpEditor +Name[cs]=Editor regulárnÃch výrazů +Name[et]=Regulaaravaldiste redaktor +Name[fa]=KRegExp ویرایشگر +Name[hi]=के-रेग-à¤à¤•à¥à¤¸à¤ª-à¤à¤¡à¥€à¤Ÿà¤° +Name[pa]=KRegExp ਸੰਪਾਦਕ +Name[pl]=Edytor wyrażeÅ„ regularnych +Name[sv]=Kregexpeditor +Name[ta]= KRegExp தொகà¯à®ªà¯à®ªà®¿ +Name[tg]=KМуҳаррири Ифодаҳои Муқаррарӣ +Name[wa]=Aspougneu d' erîlêyès ratourneures +Name[zh_TW]=æ£è¦è¡¨ç¤ºå¼ç·¨è¼¯å™¨ +Exec=kregexpeditor +DocPath=KRegExpEditor/index.html +GenericName=Regular Expression Editor +GenericName[ar]=Ù…Øرّر التعابير النظامية +GenericName[bg]=Редактор на регулÑрни изрази +GenericName[br]=Aozer an troiennoù reolataet +GenericName[bs]=Editor regularnih izraza +GenericName[ca]=Editor d'expressions regulars +GenericName[cs]=Editor regulárnÃch výrazů +GenericName[cy]=Golygydd Mynegiadau Rheolaidd +GenericName[da]=Editor for regulære udtryk +GenericName[de]=Editor für reguläre Ausdrücke +GenericName[el]=ΕπεξεÏγαστής κανονικών εκφÏάσεων +GenericName[eo]=Redaktilo por regulesprimoj +GenericName[es]=Editor de expresiones regulares +GenericName[et]=Regulaaravaldiste redaktor +GenericName[eu]=Adierazpen Erregularren Editorea +GenericName[fa]=ویرایشگر عبارت منظم +GenericName[fi]=Säännöllisten lausekkeiden muokkain +GenericName[fr]=Éditeur d'expressions régulières +GenericName[ga]=Eagarthóir Sloinn IonadaÃochta +GenericName[he]=עורך ×‘×™×˜×•×™×™× ×¨×’×•×œ×¨×™×™× +GenericName[hi]=रेगà¥à¤²à¤° à¤à¤•à¥à¤¸à¤ªà¥à¤°à¥‡à¤¶à¤¨ संपादक +GenericName[hu]=KifejezésszerkesztÅ‘ +GenericName[is]=Ritill fyrir reglulegar segðir +GenericName[it]=Editor di espressioni regolari +GenericName[ja]=æ£è¦è¡¨ç¾ã‚¨ãƒ‡ã‚£ã‚¿ +GenericName[ka]=მáƒáƒ ტივი გáƒáƒ›áƒáƒ¡áƒáƒ®áƒ£áƒšáƒ”ბის რედáƒáƒ¥áƒ¢áƒáƒ ი +GenericName[kk]=Үлгі өрнегінің редакторы +GenericName[km]=កម្មវិធី​និពន្ធ​កន្សោម​ធម្មážáž¶ +GenericName[lt]=Ä®prastųjų iÅ¡raiÅ¡kų redaktorius +GenericName[mk]=Уредувач на регуларни изрази +GenericName[ms]=Penyunting Ungkapan Nalar (regexp) +GenericName[nb]=Tekstbehandler for regulære uttrykk +GenericName[nds]=Editor för Regulere Utdrück +GenericName[ne]=नियमित अà¤à¤¿à¤µà¥à¤¯à¤•à¥à¤¤à¤¿ समà¥à¤ªà¤¾à¤¦à¤• +GenericName[nl]=Editor voor regular expressions +GenericName[nn]=Program for skriving av regulære uttrykk +GenericName[pa]=ਨਿਯਮਤ ਸਮੀਕਰਨ ਸੰਪਾਦਕ +GenericName[pl]=Edytor wyrażeÅ„ regularnych +GenericName[pt]=Editor de Expressões Regulares +GenericName[pt_BR]=Editor de Expressões Regulares +GenericName[ro]=Editor de expresii regulate +GenericName[ru]=Редактор регулÑрных выражений +GenericName[sk]=Editor regulárnych výrazov +GenericName[sl]=Urejevalnik regularnih izrazov +GenericName[sr]=Уређивач регуларних израза +GenericName[sr@Latn]=UreÄ‘ivaÄ regularnih izraza +GenericName[sv]=Editor för reguljära uttryck +GenericName[ta]=இயலà¯à®ªà®¾à®© கூறà¯à®±à¯ தொகà¯à®ªà¯à®ªà®¾à®©à¯ +GenericName[tg]=Муҳаррири Ифодаҳои Муқаррарӣ +GenericName[tr]=Tam Ä°fade Düzenleyici +GenericName[uk]=Редактор формальних виразів +GenericName[uz]=Doimiy ifoda tahrirchi +GenericName[uz@cyrillic]=Доимий ифода таҳрирчи +GenericName[wa]=Aspougneu d' erîlêyès ratourneures +GenericName[zh_CN]=æ£è§„表达å¼ç¼–辑器 +GenericName[zh_TW]=æ£è¦è¡¨ç¤ºå¼ç·¨è¼¯å™¨ +Terminal=false +Type=Application +X-KDE-StartupNotify=true +Categories=Qt;KDE;Utility;X-KDE-More; +Icon=kregexpeditor diff --git a/kregexpeditor/kregexpeditor.svgz b/kregexpeditor/kregexpeditor.svgz Binary files differnew file mode 100644 index 0000000..a91263c --- /dev/null +++ b/kregexpeditor/kregexpeditor.svgz diff --git a/kregexpeditor/kregexpeditorfactory.cpp b/kregexpeditor/kregexpeditorfactory.cpp new file mode 100644 index 0000000..bcddd63 --- /dev/null +++ b/kregexpeditor/kregexpeditorfactory.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QT_ONLY +#include <kgenericfactory.h> +#include "kregexpeditorgui.h" +typedef K_TYPELIST_2( KRegExpEditorGUI, KRegExpEditorGUIDialog ) Products; +K_EXPORT_COMPONENT_FACTORY( libkregexpeditorgui, + KGenericFactory<Products>( "kregexpeditor" ) ) +#endif diff --git a/kregexpeditor/kregexpeditorgui.cpp b/kregexpeditor/kregexpeditorgui.cpp new file mode 100644 index 0000000..e8f8051 --- /dev/null +++ b/kregexpeditor/kregexpeditorgui.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kgenericfactory.h> + #include <kapplication.h> + #include "kregexpeditorgui.moc" +#endif + +#include "kregexpeditorgui.h" +// #include <unistd.h> // DO I need this? +#include <stdio.h> +#include "kregexpeditorprivate.h" +#include <qlayout.h> + +const QString KRegExpEditorGUI::version = QString::fromLocal8Bit("1.0"); + + +KRegExpEditorGUI::KRegExpEditorGUI(QWidget *parent, const char *name, + const QStringList & ) + : QWidget( parent, name) +{ + QHBoxLayout* layout = new QHBoxLayout( this, 6 ); + _editor = new KRegExpEditorPrivate( this, "_editor" ); + layout->addWidget( _editor ); + connect( _editor, SIGNAL( canUndo(bool) ), this, SIGNAL( canUndo(bool) ) ); + connect( _editor, SIGNAL( canRedo(bool) ), this, SIGNAL( canRedo(bool) ) ); + connect( _editor, SIGNAL( changes(bool) ), this, SIGNAL( changes(bool) ) ); +} + +QString KRegExpEditorGUI::regExp() const +{ + return _editor->regexp(); +} + +void KRegExpEditorGUI::redo() +{ + _editor->slotRedo(); +} + +void KRegExpEditorGUI::undo() +{ + _editor->slotUndo(); +} + +void KRegExpEditorGUI::setRegExp( const QString ®exp ) +{ + _editor->slotSetRegexp( regexp ); +} + +KRegExpEditorGUIDialog::KRegExpEditorGUIDialog( QWidget *parent, + const char *name, + const QStringList & ) + : KDialogBase( KDialogBase::Plain, i18n("Regular Expression Editor"), + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help, KDialogBase::Ok, + parent, name ? name : "KRegExpDialog" ) +{ + QFrame* frame = plainPage(); + QVBoxLayout* layout = new QVBoxLayout( frame, 6 ); + layout->setAutoAdd( true ); + _editor = new KRegExpEditorGUI( frame ); + + connect( _editor, SIGNAL( canUndo(bool) ), this, SIGNAL( canUndo(bool) ) ); + connect( _editor, SIGNAL( canRedo(bool) ), this, SIGNAL( canRedo(bool) ) ); + connect( _editor, SIGNAL( changes(bool) ), this, SIGNAL( changes(bool) ) ); + resize( 640, 400 ); + + setHelp( QString::null, QString::fromLocal8Bit( "KRegExpEditor" ) ); +#ifdef QT_ONLY + connect( this, SIGNAL( helpClicked() ), _editor, SLOT( showHelp() ) ); +#endif +} + + +QString KRegExpEditorGUIDialog::regExp() const +{ + return _editor->regExp(); +} + +void KRegExpEditorGUIDialog::setRegExp( const QString ®exp ) +{ + _editor->setRegExp( regexp ); +} + +void KRegExpEditorGUIDialog::redo() +{ + _editor->redo(); +} + +void KRegExpEditorGUIDialog::undo() +{ + _editor->undo(); +} + +void KRegExpEditorGUIDialog::doSomething( QString method, void* arguments ) +{ + _editor->doSomething( method, arguments ); +} + +void KRegExpEditorGUI::doSomething( QString method, void* arguments ) +{ + if ( method == QString::fromLatin1( "setCaseSensitive" ) ) { + _editor->setCaseSensitive( (bool) arguments ); + } + else if ( method == QString::fromLatin1("setMinimal") ) { + _editor->setMinimal( (bool) arguments ); + } + else if ( method == QString::fromLatin1("setSyntax") ) { + _editor->setSyntax( *((QString*) arguments) ); + } + else if ( method == QString::fromLatin1("setAllowNonQtSyntax") ) { + _editor->setAllowNonQtSyntax( (bool) arguments ); + } + else { + qFatal( "%s", tr("Method '%1' is not valid!").arg(method).latin1() ); + } +} + +void KRegExpEditorGUIDialog::setMatchText( const QString& txt ) +{ + _editor->setMatchText( txt ); +} + +void KRegExpEditorGUI::setMatchText( const QString& txt ) +{ + _editor->setMatchText( txt ); +} + + +void KRegExpEditorGUI::showHelp() +{ +#ifdef QT_ONLY + _editor->showHelp(); +#else + kapp->invokeHelp( QString::null, QString::fromLocal8Bit( "KRegExpEditor" ) ); +#endif +} + +#ifndef QT_ONLY +typedef K_TYPELIST_2( KRegExpEditorGUI, KRegExpEditorGUIDialog ) Products; +K_EXPORT_COMPONENT_FACTORY( libkregexpeditorgui, + KGenericFactory<Products>( "kregexpeditor" ) ) +#endif diff --git a/kregexpeditor/kregexpeditorgui.desktop b/kregexpeditor/kregexpeditorgui.desktop new file mode 100644 index 0000000..23e3896 --- /dev/null +++ b/kregexpeditor/kregexpeditorgui.desktop @@ -0,0 +1,62 @@ +[Desktop Entry] +Type=Service +Name=RegExp Editor Widget +Name[af]=Regexp Redigeerder Gui-element +Name[ar]=أداة Ù…Øرر التعابير النظامية +Name[az]=QaydalıİfadÉ™ Editor PÉ™ncÉ™rÉ™si +Name[bg]=Редактор на регулÑрни изрази +Name[ca]=Estri editor RegExp +Name[cs]=Editor regulárnÃch výrazů +Name[cy]=Teclyn Golygydd RegExp +Name[da]=RegExp Editor-kontrol +Name[de]=RegExp-Bedienelement +Name[el]=ΓÏαφικό συστατικό επεξεÏγασίας κανονικών εκφÏάσεων +Name[eo]=Redaktilo por regulesprimoj +Name[es]=Ventana de edición RegExp +Name[et]=Regulaaravaldiste redaktori komponent +Name[eu]=RegExp Editore Widgeta +Name[fa]=RegExp عنصر ویرایشگر +Name[fi]=Säännöllisten lauseiden muokkain +Name[fr]=Composant éditeur d'exp. rég. +Name[ga]=Giuirléid Eagarthóireachta Sloinn IonadaÃochta +Name[he]=פריט עורך ×”×‘×™×˜×•×™×™× ×”×¡×“×™×¨×™× +Name[hi]=रेग-à¤à¤•à¥à¤¸à¤ªà¥€ संपादक विजेट +Name[hr]=Widget za ureÄ‘ivanje RegExp-a (regularnih izraza) +Name[hu]=Grafikus objektum reguláris kifejezések szerkesztéséhez +Name[it]=Elemento grafico dell'editor di espressioni regolari +Name[ja]=æ£è¦è¡¨ç¾ã‚¨ãƒ‡ã‚£ã‚¿ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆ +Name[kk]=Үлгі өрнегінің өңдеу бөлшегі +Name[km]=ážœážáŸ’ážáž»â€‹áž˜áž¾áž›â€‹ážƒáž¾áž‰áž€áž˜áŸ’មវិធី​និពន្ធ RegExp +Name[lt]=RegExp redaktoriaus valdiklis +Name[lv]=RegExp Redaktora Widžets +Name[mk]=графичка контрола за уредување RegExp +Name[ms]=Wijet Penyunting RegExp +Name[mt]=Editur ta' RegExp +Name[nb]=Skjermelement RegExp tekstbehandler +Name[nds]=RegExp Editor-Bedeenelement +Name[ne]=RegExp समà¥à¤ªà¤¾à¤¦à¤• विजेट +Name[nn]=Skjermelement for redigering av regulære uttrykk +Name[pl]=Edytor wyrażeÅ„ regularnych +Name[pt]=Item de Edição de Expressões Regulares +Name[pt_BR]=Widget do Editor de Expressões Regulares +Name[ro]=Componentă editare expresii regulate +Name[ru]=Виджет редактора регулÑрных выражений +Name[sk]=Prvok Editor regulárnych výrazov +Name[sl]=Gradnik urejevalnika RegExp +Name[sr]=Контрола уређивача регуларних израза +Name[sr@Latn]=Kontrola ureÄ‘ivaÄa regularnih izraza +Name[sv]=Grafisk komponent för att redigera reguljära uttryck +Name[ta]= RegExp தொகà¯à®ªà¯à®ªà®¾à®©à¯ சாளரம௠+Name[tg]=Ҷузъи Муҳаррири Ифодаҳои Муқаррарӣ +Name[th]=คà¸à¸™à¹‚ทรลà¹à¸à¹‰à¹„ข RegExp +Name[tr]=RegExp Düzenleyici Aleti +Name[uk]=Віджет редактору регулÑрних виразів +Name[ven]=Widget ya musengulusi wa RegExp +Name[wa]=Ahesse aspougneu d' erîlêyès ratourneures +Name[xh]=RegExp Umhleli we Widget +Name[zh_CN]=æ£åˆ™è¡¨è¾¾å¼ç¼–辑器部件 +Name[zh_TW]=æ£è¦è¡¨ç¤ºå¼ç·¨è¼¯å°ç¨‹å¼ +Name[zu]=RegExp Umhleli we-widget +X-KDE-Library=libkregexpeditorgui +InitialPreference=2 +ServiceTypes=KRegExpEditor/KRegExpEditor diff --git a/kregexpeditor/kregexpeditorgui.h b/kregexpeditor/kregexpeditorgui.h new file mode 100644 index 0000000..6bcd5e6 --- /dev/null +++ b/kregexpeditor/kregexpeditorgui.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef kregexpeditorgui_h +#define kregexpeditorgui_h + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <kdialogbase.h> +#endif + +#include <kregexpeditorinterface.h> + +class KRegExpEditorPrivate; + +/** + Regular Expression Editor. + + @author Jesper Kjær Pedersen <blackie@kde.org> + @version 0.1 + **/ +class KDE_EXPORT KRegExpEditorGUI :public QWidget, public KRegExpEditorInterface +{ + Q_OBJECT + Q_PROPERTY( QString regexp READ regExp WRITE setRegExp ) +public: + KRegExpEditorGUI( QWidget *parent, const char *name = 0, + const QStringList & = QStringList() ); + virtual QString regExp() const; + + static const QString version; + +signals: + /** This signal tells whether undo is available. */ + virtual void canRedo( bool ); + virtual void canUndo( bool ); + virtual void changes( bool ); + +public slots: + virtual void redo(); + virtual void undo(); + virtual void setRegExp( const QString ®exp ); + virtual void doSomething( QString method, void* arguments ); + virtual void setMatchText( const QString& ); + void showHelp(); + +private: + KRegExpEditorPrivate* _editor; +}; + +class KDE_EXPORT KRegExpEditorGUIDialog : public KDialogBase, public KRegExpEditorInterface +{ + Q_OBJECT + Q_PROPERTY( QString regexp READ regExp WRITE setRegExp ) +public: + KRegExpEditorGUIDialog( QWidget *parent, const char *name, const QStringList &args ); + + virtual QString regExp() const; + +signals: + /** This signal tells whether undo is available. */ + virtual void canRedo( bool ); + virtual void canUndo( bool ); + virtual void changes( bool ); + +public slots: + virtual void redo(); + virtual void undo(); + virtual void setRegExp( const QString ®exp ); + virtual void doSomething( QString method, void* arguments ); + virtual void setMatchText( const QString& ); + +private: + KRegExpEditorGUI *_editor; +}; + +#endif + diff --git a/kregexpeditor/kregexpeditorprivate.cpp b/kregexpeditor/kregexpeditorprivate.cpp new file mode 100644 index 0000000..b13a655 --- /dev/null +++ b/kregexpeditor/kregexpeditorprivate.cpp @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kiconloader.h> + #include <kstandarddirs.h> + #include <kmessagebox.h> + #include "kregexpeditorprivate.moc" +#endif + +#include <qlineedit.h> +#include <qtooltip.h> +#include <qtoolbutton.h> +#include "kregexpeditorprivate.h" +#include "scrollededitorwindow.h" +#include "regexpbuttons.h" +//#include <unistd.h> // What do I need this for? +#include <stdio.h> +#include "infopage.h" +#include <qsplitter.h> +#include <qdockarea.h> +#include "userdefinedregexps.h" +#include "auxbuttons.h" +#include <qaccel.h> +#include <qtimer.h> +#include "verifier.h" +#include <qfile.h> +#include "verifybuttons.h" +#include <qwhatsthis.h> + +KRegExpEditorPrivate::KRegExpEditorPrivate(QWidget *parent, const char *name) + : QWidget(parent, name), _updating( false ), _autoVerify( true ) +{ + setMinimumSize(730,300); + QDockArea* area = new QDockArea( Horizontal, QDockArea::Normal, this ); + area->setMinimumSize(2,2); + QDockArea* verArea1 = new QDockArea( Vertical, QDockArea::Normal, this ); + verArea1->setMinimumSize(2,2); + QDockArea* verArea2 = new QDockArea( Vertical, QDockArea::Reverse, this ); + verArea2->setMinimumSize(2,2); + + // The DockWindows. + _regExpButtons = new RegExpButtons( area, "KRegExpEditorPrivate::regExpButton" ); + _verifyButtons = new VerifyButtons( area, "KRegExpEditorPrivate::VerifyButtons" ); + _auxButtons = new AuxButtons( area, "KRegExpEditorPrivate::AuxButtons" ); + _userRegExps = new UserDefinedRegExps( verArea1, "KRegExpEditorPrivate::userRegExps" ); + _userRegExps->setResizeEnabled( true ); + QWhatsThis::add( _userRegExps, i18n( "In this window you will find predefined regular expressions. Both regular expressions " + "you have developed and saved, and regular expressions shipped with the system." )); + + // Editor window + _editor = new QSplitter( Vertical, this, "KRegExpEditorPrivate::_editor" ); + + _scrolledEditorWindow = + new RegExpScrolledEditorWindow( _editor, "KRegExpEditorPrivate::_scrolledEditorWindow" ); + QWhatsThis::add( _scrolledEditorWindow, i18n( "In this window you will develop your regular expressions. " + "Select one of the actions from the action buttons above, and click the mouse in this " + "window to insert the given action.")); + + _info = new InfoPage( this, "_info" ); + _verifier = new Verifier( _editor, "KRegExpEditorPrivate::_verifier" ); + connect( _verifier, SIGNAL( textChanged() ), this, SLOT( maybeVerify() ) ); + QWhatsThis::add( _verifier, i18n("Type in some text in this window, and see what the regular expression you have developed matches.<p>" + "Each second match will be colored in red and each other match will be colored blue, simply so you " + "can distinguish them from each other.<p>" + "If you select part of the regular expression in the editor window, then this part will be " + "highlighted - This allows you to <i>debug</i> your regular expressions") ); + + _editor->hide(); + _editor->setSizes( QValueList<int>() << _editor->height()/2 << _editor->height()/2 ); + + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, 6, "KRegExpEditorPrivate::topLayout" ); + topLayout->addWidget( area ); + QHBoxLayout* rows = new QHBoxLayout; // I need to cal addLayout explicit to get stretching right. + topLayout->addLayout( rows, 1 ); + + rows->addWidget( verArea1 ); + rows->addWidget( _editor, 1 ); + rows->addWidget( _info, 1 ); + rows->addWidget( verArea2 ); + + // Connect the buttons + connect( _regExpButtons, SIGNAL( clicked( int ) ), _scrolledEditorWindow, SLOT( slotInsertRegExp( int ) ) ); + connect( _regExpButtons, SIGNAL( doSelect() ), _scrolledEditorWindow, SLOT( slotDoSelect() ) ); + connect( _userRegExps, SIGNAL( load( RegExp* ) ), _scrolledEditorWindow, SLOT( slotInsertRegExp( RegExp* ) ) ); + + connect( _regExpButtons, SIGNAL( clicked( int ) ), _userRegExps, SLOT( slotUnSelect() ) ); + connect( _regExpButtons, SIGNAL( doSelect() ), _userRegExps, SLOT( slotUnSelect() ) ); + connect( _userRegExps, SIGNAL( load( RegExp* ) ), _regExpButtons, SLOT( slotUnSelect() ) ); + + connect( _scrolledEditorWindow, SIGNAL( doneEditing() ), _regExpButtons, SLOT( slotSelectNewAction() ) ); + connect( _scrolledEditorWindow, SIGNAL( doneEditing() ), _userRegExps, SLOT( slotSelectNewAction() ) ); + + connect( _regExpButtons, SIGNAL( clicked( int ) ), this, SLOT( slotShowEditor() ) ); + connect( _userRegExps, SIGNAL( load( RegExp* ) ), this, SLOT( slotShowEditor() ) ); + connect( _regExpButtons, SIGNAL( doSelect() ), this, SLOT( slotShowEditor() ) ); + + connect( _scrolledEditorWindow, SIGNAL( savedRegexp() ), _userRegExps, SLOT( slotPopulateUserRegexps() ) ); + + connect( _auxButtons, SIGNAL( undo() ), this, SLOT( slotUndo() ) ); + connect( _auxButtons, SIGNAL( redo() ), this, SLOT( slotRedo() ) ); + connect( _auxButtons, SIGNAL( cut() ), _scrolledEditorWindow, SLOT( slotCut() ) ); + connect( _auxButtons, SIGNAL( copy() ), _scrolledEditorWindow, SLOT( slotCopy() ) ); + connect( _auxButtons, SIGNAL( paste() ), _scrolledEditorWindow, SLOT( slotPaste() ) ); + connect( _auxButtons, SIGNAL( save() ), _scrolledEditorWindow, SLOT( slotSave() ) ); + connect( _verifyButtons, SIGNAL( autoVerify( bool ) ), this, SLOT( setAutoVerify( bool ) ) ); + connect( _verifyButtons, SIGNAL( verify() ), this, SLOT( doVerify() ) ); + connect( _verifyButtons, SIGNAL( changeSyntax( const QString& ) ), this, SLOT( setSyntax( const QString& ) ) ); + + connect( this, SIGNAL( canUndo( bool ) ), _auxButtons, SLOT( slotCanUndo( bool ) ) ); + connect( this, SIGNAL( canRedo( bool ) ), _auxButtons, SLOT( slotCanRedo( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( anythingSelected( bool ) ), _auxButtons, SLOT( slotCanCut( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( anythingSelected( bool ) ), _auxButtons, SLOT( slotCanCopy( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( anythingOnClipboard( bool ) ), _auxButtons, SLOT( slotCanPaste( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( canSave( bool ) ), _auxButtons, SLOT( slotCanSave( bool ) ) ); + + connect( _scrolledEditorWindow, SIGNAL( verifyRegExp() ), this, SLOT( maybeVerify() ) ); + + connect( _verifyButtons, SIGNAL( loadVerifyText( const QString& ) ), this, SLOT( setVerifyText( const QString& ) ) ); + + // connect( _verifier, SIGNAL( countChanged( int ) ), _verifyButtons, SLOT( setMatchCount( int ) ) ); + + // Qt anchors do not work for <pre>...</pre>, thefore scrolling to next/prev match + // do not work. Enable this when they work. + // connect( _verifyButtons, SIGNAL( gotoFirst() ), _verifier, SLOT( gotoFirst() ) ); + // connect( _verifyButtons, SIGNAL( gotoPrev() ), _verifier, SLOT( gotoPrev() ) ); + // connect( _verifyButtons, SIGNAL( gotoNext() ), _verifier, SLOT( gotoNext() ) ); + // connect( _verifyButtons, SIGNAL( gotoLast() ), _verifier, SLOT( gotoLast() ) ); + // connect( _verifier, SIGNAL( goForwardPossible( bool ) ), _verifyButtons, SLOT( enableForwardButtons( bool ) ) ); + // connect( _verifier, SIGNAL( goBackwardPossible( bool ) ), _verifyButtons, SLOT( enableBackwardButtons( bool ) ) ); + + _auxButtons->slotCanPaste( false ); + _auxButtons->slotCanCut( false ); + _auxButtons->slotCanCopy( false ); + _auxButtons->slotCanSave( false ); + + + // Line Edit + QHBoxLayout* layout = new QHBoxLayout( topLayout, 6 ); + QLabel* label = new QLabel( i18n("ASCII syntax:"), this ); + layout->addWidget( label ); + clearButton = new QToolButton( this ); + const QString icon( QString::fromLatin1( QApplication::reverseLayout() ? "clear_left" : "locationbar_erase" ) ); + QIconSet clearIcon = SmallIconSet( icon ); + clearButton->setIconSet( clearIcon ); + layout->addWidget( clearButton ); + QToolTip::add( clearButton, i18n("Clear expression") ); + _regexpEdit = new QLineEdit( this ); + layout->addWidget( _regexpEdit ); + QWhatsThis::add( _regexpEdit, i18n( "This is the regular expression in ASCII syntax. You are likely only " + "to be interested in this if you are a programmer, and need to " + "develop a regular expression using QRegExp.<p>" + "You may develop your regular expression both by using the graphical " + "editor, and by typing the regular expression in this line edit.") ); + +#ifdef QT_ONLY + QPixmap pix( "icons/error.png" ); +#else + QPixmap pix = KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/error.png") ), KIcon::Toolbar ); +#endif + _error = new QLabel( this ); + _error->setPixmap( pix ); + layout->addWidget( _error ); + _error->hide(); + + _timer = new QTimer(this); + + connect( _scrolledEditorWindow, SIGNAL( change() ), this, SLOT( slotUpdateLineEdit() ) ); + connect( _regexpEdit, SIGNAL(textChanged( const QString& ) ), this, SLOT( slotTriggerUpdate() ) ); + connect( _timer, SIGNAL( timeout() ), this, SLOT( slotTimeout() ) ); + connect( clearButton, SIGNAL( clicked() ), _regexpEdit, SLOT( clear() ) ); + + // Push an initial empty element on the stack. + _undoStack.push( _scrolledEditorWindow->regExp() ); + _redoStack.setAutoDelete( true ); + + QAccel* accel = new QAccel( this ); + accel->connectItem( accel->insertItem( CTRL+Key_Z ), this, SLOT( slotUndo() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_R ), this, SLOT( slotRedo() ) ); + + setSyntax( QString::fromLatin1( "Qt" ) ); +} + +QString KRegExpEditorPrivate::regexp() +{ + RegExp* regexp = _scrolledEditorWindow->regExp(); + QString res = RegExpConverter::current()->toStr( regexp, false ); + delete regexp; + return res; +} + +void KRegExpEditorPrivate::slotUpdateEditor( const QString & txt) +{ + _updating = true; + bool ok; + if ( !RegExpConverter::current()->canParse() ) { + // This can happend if the application set a text through the API. + } + else { + RegExp* result = RegExpConverter::current()->parse( txt, &ok ); + if ( ok ) { + QPtrList<CompoundRegExp> list = _userRegExps->regExps(); + for ( QPtrListIterator<CompoundRegExp> it( list ); *it; ++it ) { + result->replacePart( *it ); + } + + _scrolledEditorWindow->slotSetRegExp( result ); + _error->hide(); + maybeVerify( ); + recordUndoInfo(); + result->check( _errorMap ); + } + else { + _error->show(); + if ( _autoVerify ) + _verifier->clearRegexp(); + } + delete result; + } + _updating = false; +} + +void KRegExpEditorPrivate::slotUpdateLineEdit() +{ + if ( _updating ) + return; + _updating = true; + + RegExp* regexp = _scrolledEditorWindow->regExp(); + regexp->check( _errorMap ); + + QString str = RegExpConverter::current()->toStr( regexp, false ); + _regexpEdit->setText( str ); + delete regexp; + + recordUndoInfo(); + + _updating = false; +} + +void KRegExpEditorPrivate::recordUndoInfo() +{ + Q_ASSERT( _updating ); + + // Update undo/redo stacks + RegExp* regexp = _scrolledEditorWindow->regExp(); + if ( regexp->toXmlString() != _undoStack.top()->toXmlString() ) { + _undoStack.push( regexp ); + _redoStack = QPtrStack<RegExp>(); + emitUndoRedoSignals(); + } +} + +void KRegExpEditorPrivate::slotRedo() +{ + if ( _redoStack.count() != 0 ) { + _undoStack.push(_redoStack.pop()); + _scrolledEditorWindow->slotSetRegExp( _undoStack.top() ); + slotUpdateLineEdit(); + emitUndoRedoSignals(); + maybeVerify(); + } +} + +void KRegExpEditorPrivate::slotUndo() +{ + if ( _undoStack.count() > 1 ) { + _redoStack.push(_undoStack.pop()); + _scrolledEditorWindow->slotSetRegExp( _undoStack.top() ); + slotUpdateLineEdit(); + emitUndoRedoSignals(); + maybeVerify(); + } +} + +void KRegExpEditorPrivate::slotShowEditor() +{ + _info->hide(); + _editor->show(); +} + +void KRegExpEditorPrivate::emitUndoRedoSignals() +{ + emit canUndo( _undoStack.count() > 1 ); + emit changes( _undoStack.count() > 1 ); + emit canRedo( _redoStack.count() > 0 ); +} + +void KRegExpEditorPrivate::slotSetRegexp( QString regexp ) +{ + _regexpEdit->setText( regexp ); +} + +void KRegExpEditorPrivate::slotTriggerUpdate() +{ + /* ### Guess this timeout value should be configurable somewhere, or (even + * better: do some kind of benchmark each time the editor view gets updated + * to measure how long it takes on the client system to render the editor + * with the current complexity. That way we'd get good response times for + * simple regexps, and flicker-free display for complex regexps. + * - Frerich + */ + if ( !_updating ) { + _timer->start( 300, true ); + slotShowEditor(); + } +} + +void KRegExpEditorPrivate::slotTimeout() +{ + slotUpdateEditor( _regexpEdit->text() ); +} + +void KRegExpEditorPrivate::setMatchText( const QString& text ) +{ + bool autoVerify = _autoVerify; + _autoVerify = false; + _verifier->setText( text ); + _autoVerify = autoVerify; +} + +void KRegExpEditorPrivate::maybeVerify() +{ + if ( _autoVerify ) + doVerify(); + else + _verifyButtons->setMatchCount(-1); +} + +void KRegExpEditorPrivate::doVerify() +{ + bool autoVerify = _autoVerify; // prevent loop due to verify emit changed, which calls maybeVerify + _autoVerify = false; + RegExp* regexp = _scrolledEditorWindow->regExp(); + + _verifier->verify( RegExpConverter::current()->toStr( regexp, true ) ); + delete regexp; + _autoVerify = autoVerify; +} + +void KRegExpEditorPrivate::setAutoVerify( bool on ) +{ + _autoVerify = on; + if ( !_autoVerify ) + _verifier->clearRegexp(); + else + doVerify(); +} + +void KRegExpEditorPrivate::setVerifyText( const QString& fileName ) +{ + bool autoVerify = _autoVerify; + _autoVerify = false; + QFile file( fileName ); + if ( !file.open( IO_ReadOnly ) ) { + KMessageBox::sorry(0, i18n("Could not open file '%1' for reading").arg( fileName ) ); + } + else { + QTextStream s( &file ); + QString txt = s.read(); + file.close(); + RegExp* regexp = _scrolledEditorWindow->regExp(); + _verifier->setText( txt ); + _verifier->verify( RegExpConverter::current()->toStr( regexp, true ) ); + delete regexp; + } + _autoVerify = autoVerify; +} + +void KRegExpEditorPrivate::setCaseSensitive( bool b ) +{ + _verifier->setCaseSensitive( b ); +} + +void KRegExpEditorPrivate::setMinimal( bool b ) +{ + _verifier->setMinimal( b ); +} + +void KRegExpEditorPrivate::setSyntax( const QString& syntax ) +{ + RegExpConverter* converter = _verifyButtons->setSyntax( syntax ); + RegExpConverter::setCurrent( converter ); + if ( converter->canParse() ) { + _regexpEdit->setReadOnly( false ); + _regexpEdit->setBackgroundMode( Qt::PaletteBase ); + } + else { + _regexpEdit->setReadOnly( true ); + _regexpEdit->setBackgroundMode( Qt::PaletteBackground ); + } + _regExpButtons->setFeatures( converter->features() ); + _verifier->setHighlighter( converter->highlighter(_verifier) ); + slotUpdateLineEdit(); +} + +void KRegExpEditorPrivate::showHelp() +{ + _info->show(); + _editor->hide(); +} + +void KRegExpEditorPrivate::setAllowNonQtSyntax( bool b ) +{ + _verifyButtons->setAllowNonQtSyntax( b ); +} diff --git a/kregexpeditor/kregexpeditorprivate.h b/kregexpeditor/kregexpeditorprivate.h new file mode 100644 index 0000000..2e40fad --- /dev/null +++ b/kregexpeditor/kregexpeditorprivate.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef kregexpeditorprivate_h +#define kregexpeditorprivate_h + +#include <qlabel.h> +#include <qptrstack.h> +#include "regexp.h" +#include "errormap.h" +class QTimer; + +class RegExpScrolledEditorWindow; +class QLineEdit; +class InfoPage; +class UserDefinedRegExps; +class QSplitter; +class Verifier; +class VerifyButtons; +class AuxButtons; +class RegExpLineEdit; +class RegExpConverter; +class RegExpButtons; +class QToolButton; + +/** + Widget used to build a regular expression + + @author Jesper K. Pedersen <blackie@kde.org> + @version 0.1 +**/ +class KRegExpEditorPrivate :public QWidget +{ + Q_OBJECT + +public: + KRegExpEditorPrivate( QWidget *parent, const char *name = 0 ); + QString regexp(); + void setMinimal( bool ); + void setCaseSensitive( bool ); + void setAllowNonQtSyntax( bool ); + +protected slots: + void slotUpdateEditor( const QString & ); + void slotUpdateLineEdit(); + void slotShowEditor(); + void slotTriggerUpdate(); + void slotTimeout(); + void maybeVerify(); + void doVerify(); + void setAutoVerify( bool ); + void setVerifyText( const QString& fileName ); + +public slots: + void slotUndo(); + void slotRedo(); + void slotSetRegexp( QString regexp ); + void setMatchText( const QString& text ); + void setSyntax( const QString& ); + void showHelp(); + +signals: + void canUndo( bool ); + void canRedo( bool ); + void changes( bool ); + +protected: + void recordUndoInfo(); + void emitUndoRedoSignals(); + +private: + RegExpScrolledEditorWindow* _scrolledEditorWindow; + RegExpButtons* _regExpButtons; + VerifyButtons* _verifyButtons; + AuxButtons *_auxButtons; + InfoPage* _info; + QLineEdit* _regexpEdit; + QSplitter* _editor; + bool _updating; + QLabel* _error; + QPtrStack<RegExp> _undoStack; + QPtrStack<RegExp> _redoStack; + UserDefinedRegExps* _userRegExps; + QTimer* _timer; + Verifier* _verifier; + bool _autoVerify; + ErrorMap _errorMap; + QToolButton *clearButton; +}; + +#endif + diff --git a/kregexpeditor/limitedcharlineedit.cpp b/kregexpeditor/limitedcharlineedit.cpp new file mode 100644 index 0000000..9631603 --- /dev/null +++ b/kregexpeditor/limitedcharlineedit.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "limitedcharlineedit.h" +#include <qvalidator.h> + +/** + @internal + A Validator for the @ref LimitedCharLineEdit +*/ +class Validator :public QValidator +{ +public: + Validator( LimitedCharLineEdit::Mode mode, QWidget* parent ) + :QValidator( parent, "Validator" ), _mode(mode) + { + } + + virtual QValidator::State validate( QString& txt, int & /*pos*/ ) const + { + if ( _mode == LimitedCharLineEdit::NORMAL || + (_mode == LimitedCharLineEdit::HEX && + QRegExp(QString::fromLocal8Bit("^[0-9A-Fa-f]*$")).search( txt ) != -1) || + (_mode == LimitedCharLineEdit::OCT && + QRegExp(QString::fromLocal8Bit("^[0-7]*$")).search( txt ) != -1 ) ) { + return QValidator::Acceptable; + } + else { + return QValidator::Invalid; + } + } + +private: + LimitedCharLineEdit::Mode _mode; +}; + + +void LimitedCharLineEdit::keyPressEvent ( QKeyEvent *event ) +{ + QLineEdit::keyPressEvent( event ); + if ( text().length() == _count && !event->text().isNull() ) + focusNextPrevChild(true); +} + +LimitedCharLineEdit::LimitedCharLineEdit( Mode mode, QWidget* parent, const char* name ) + :QLineEdit( parent, name ), _mode(mode) +{ + if ( mode == NORMAL ) + _count = 1; + else if ( mode == HEX ) + _count = 4; + else + _count = 4; + + setMaxLength( _count ); + setFixedSize( fontMetrics().width('A')*5+5, sizeHint().height()); + + setValidator( new Validator( mode, this ) ); +} + + diff --git a/kregexpeditor/limitedcharlineedit.h b/kregexpeditor/limitedcharlineedit.h new file mode 100644 index 0000000..d4654c6 --- /dev/null +++ b/kregexpeditor/limitedcharlineedit.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __limitedcharlineedit +#define __limitedcharlineedit + +#include <qlineedit.h> + +/** + QLineEdit which only accepts a prespecified number of character. + @internal +*/ +class LimitedCharLineEdit :public QLineEdit +{ +public: + enum Mode { NORMAL = 0, HEX = 1, OCT = 2 }; + + LimitedCharLineEdit(Mode mode, QWidget* parent, const char *name = 0); + +protected: + virtual void keyPressEvent ( QKeyEvent * ); + +private: + Mode _mode; + unsigned int _count; +}; + +#endif + diff --git a/kregexpeditor/lookaheadregexp.cpp b/kregexpeditor/lookaheadregexp.cpp new file mode 100644 index 0000000..7415ca4 --- /dev/null +++ b/kregexpeditor/lookaheadregexp.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "lookaheadregexp.h" +#include "errormap.h" + +LookAheadRegExp::LookAheadRegExp( bool selected, TYPE tp, RegExp* child ) + : RegExp( selected ), _child( child ), _tp( tp ) +{ + if ( child ) + addChild( child ); +} + +bool LookAheadRegExp::check( ErrorMap& map, bool , bool last ) +{ + if ( !last ) { + map.lookAheadError(); + } + return true; +} + + +QDomNode LookAheadRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top; + if ( _tp == POSITIVE ) + top = doc->createElement( QString::fromLocal8Bit("PositiveLookAhead") ); + else + top = doc->createElement( QString::fromLocal8Bit("NegativeLookAhead") ); + + top.appendChild( _child->toXml( doc ) ); + return top; +} + +bool LookAheadRegExp::load( QDomElement top, const QString& version ) +{ + _child = readRegExp( top, version ); + if ( _child ) { + addChild( _child ); + return true; + } + else + return false; +} + + +bool LookAheadRegExp::operator==( const RegExp& other ) const +{ + if ( type() != other.type() ) + return false; + + const LookAheadRegExp& theOther = dynamic_cast<const LookAheadRegExp&>( other ); + + if ( lookAheadType() != theOther.lookAheadType() ) + return false; + + return ( *_child == *(theOther._child) ); +} diff --git a/kregexpeditor/lookaheadregexp.h b/kregexpeditor/lookaheadregexp.h new file mode 100644 index 0000000..9021710 --- /dev/null +++ b/kregexpeditor/lookaheadregexp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __LOOKAHEADREGEXP_H +#define __LOOKAHEADREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `repeated content' regular expression + @internal +*/ +class LookAheadRegExp :public RegExp +{ +public: + enum TYPE { POSITIVE, NEGATIVE }; + + LookAheadRegExp( bool selected, TYPE tp, RegExp* child = 0); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + RegExp* child() const { return _child; } + TYPE lookAheadType() const { return _tp; } + virtual RegExpType type() const { return LOOKAHEAD;} + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ) { _child->replacePart( replacement ); } + +private: + RegExp* _child; + TYPE _tp; +}; + +#endif // __LOOKAHEADREGEXP_H diff --git a/kregexpeditor/lookaheadwidget.cpp b/kregexpeditor/lookaheadwidget.cpp new file mode 100644 index 0000000..b724a3c --- /dev/null +++ b/kregexpeditor/lookaheadwidget.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include "lookaheadwidget.moc" +#endif + +#include "lookaheadwidget.h" +#include "lookaheadregexp.h" +#include "concwidget.h" +#include <qpainter.h> + +LookAheadWidget::LookAheadWidget( RegExpEditorWindow* editorWindow, RegExpType tp, QWidget* parent, const char* name ) + :SingleContainerWidget(editorWindow, parent, name ? name : "LookAheadWidget" ), _tp(tp) +{ + _child = new ConcWidget( editorWindow, this ); + init(); +} + +LookAheadWidget::LookAheadWidget( LookAheadRegExp* regexp, RegExpEditorWindow* editorWindow, RegExpType tp, + QWidget* parent, const char* name ) + :SingleContainerWidget( editorWindow, parent, name ? name : "LookAheadWidget" ), _tp(tp) +{ + RegExpWidget* child = WidgetFactory::createWidget( regexp->child(), editorWindow, this ); + if ( ! (_child = dynamic_cast<ConcWidget*>( child ) ) ) + _child = new ConcWidget( editorWindow, child, this ); + + init(); +} + +void LookAheadWidget::init() +{ + if ( _tp == POSLOOKAHEAD ) + _text = i18n("Pos. Look Ahead"); + else + _text = i18n("Neg. Look Ahead"); +} + +RegExp* LookAheadWidget::regExp() const +{ + return new LookAheadRegExp( isSelected(), ( (_tp == POSLOOKAHEAD) ? LookAheadRegExp::POSITIVE : LookAheadRegExp::NEGATIVE), + _child->regExp() ); +} + +QSize LookAheadWidget::sizeHint() const +{ + // TODO: Merge with RepeatWidget::sizeHint + QFontMetrics metrics = fontMetrics(); + _textSize = metrics.size( 0, _text ); + + _childSize = _child->sizeHint(); + + int height = _textSize.height() + bdSize + _childSize.height() + bdSize + 2*pw; + int width = 2 * pw + QMAX(_childSize.width(), 4*bdSize + _textSize.width()); + return QSize(width,height); +} + +void LookAheadWidget::paintEvent( QPaintEvent *e ) +{ + // TODO: Merge with RepeatWidget::paintEvent + QSize mySize = sizeHint(); + QPainter painter(this); + + drawPossibleSelection( painter, mySize ); + + // move the child to its position and resize it. + _child->move(pw,_textSize.height()+bdSize); + _child->resize(mySize.width() - 2*pw, _childSize.height()); + + // Draw the border and the text. + int startY = _textSize.height()/2; + + // Top lines and text + painter.drawLine(pw,startY,bdSize,startY); + painter.drawText(pw+2*bdSize,0,_textSize.width(), _textSize.height(),0, _text); + int offset = pw + 3*bdSize + _textSize.width(); + painter.drawLine(offset,startY,mySize.width()-pw,startY); + + // horizontal lines + painter.drawLine(0,startY,0,mySize.height()-pw); + painter.drawLine(mySize.width()-pw,startY,mySize.width()-pw, mySize.height()-pw); + + // buttom line + painter.drawLine(0, mySize.height()-pw, mySize.width()-pw, mySize.height()-pw); + + SingleContainerWidget::paintEvent(e); +} + +RegExpWidget* LookAheadWidget::findWidgetToEdit( QPoint globalPos ) +{ + return _child->findWidgetToEdit( globalPos ); +} diff --git a/kregexpeditor/lookaheadwidget.h b/kregexpeditor/lookaheadwidget.h new file mode 100644 index 0000000..5e244b8 --- /dev/null +++ b/kregexpeditor/lookaheadwidget.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __lookaheadwidget +#define __lookaheadwidget + +#include "singlecontainerwidget.h" +class LookAheadRegExp; + +class LookAheadWidget :public SingleContainerWidget +{ + Q_OBJECT +public: + LookAheadWidget( RegExpEditorWindow* editorWindow, RegExpType tp, QWidget* parent, const char* name = 0 ); + LookAheadWidget( LookAheadRegExp* regexp, RegExpEditorWindow* editorWindow, RegExpType tp, + QWidget* parent, const char* name = 0); + + virtual RegExp* regExp() const; + virtual RegExpType type() const { return _tp; } + virtual QSize sizeHint() const; + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + + +protected: + void init(); + virtual void paintEvent( QPaintEvent *e ); + + +private: + RegExpType _tp; + QString _text; + + mutable QSize _textSize; + mutable QSize _childSize; +}; + +#endif // __lookaheadwidget diff --git a/kregexpeditor/main.cpp b/kregexpeditor/main.cpp new file mode 100644 index 0000000..bde19e9 --- /dev/null +++ b/kregexpeditor/main.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include <qapplication.h> +#else + #include <kaboutdata.h> + #include <kapplication.h> + #include <kcmdlineargs.h> + #include <klocale.h> + #include <kpushbutton.h> +#endif + +#include "kregexpeditorgui.h" +#include <qlayout.h> + +int main( int argc, char* argv[] ) +{ +#ifdef QT_ONLY + QApplication myapp( argc, argv ); +#else + KAboutData aboutData( "kregexpeditor", I18N_NOOP("RegExp Editor"), + "1.0", I18N_NOOP("Editor for Regular Expressions"), + KAboutData::License_GPL, + "(c) 2002-2003 Jesper K. Pedersen"); + KCmdLineArgs::init(argc, argv, &aboutData); + KApplication myapp; +#endif + + QDialog* top = new QDialog( 0 ); + QVBoxLayout* lay = new QVBoxLayout( top, 6 ); + + KRegExpEditorGUI* iface = new KRegExpEditorGUI( top, "_editor", QStringList() ); + iface->doSomething( QString::fromLatin1("setAllowNonQtSyntax"), (bool*) true ); + lay->addWidget( iface ); + + QHBoxLayout* lay2 = new QHBoxLayout( lay, 6 ); + KPushButton* help = new KPushButton( KStdGuiItem::help(), top ); + KPushButton* quit = new KPushButton( KStdGuiItem::quit(), top ); + + lay2->addWidget( help ); + lay2->addStretch(1); + lay2->addWidget( quit ); + + QObject::connect( help, SIGNAL( clicked() ), iface, SLOT( showHelp() ) ); + QObject::connect( quit, SIGNAL( clicked() ), qApp, SLOT( quit() ) ); + + top->show(); + QObject::connect( qApp, SIGNAL( lastWindowClosed() ), qApp, SLOT( quit() ) ); + myapp.exec(); +} + diff --git a/kregexpeditor/multicontainerwidget.cpp b/kregexpeditor/multicontainerwidget.cpp new file mode 100644 index 0000000..b4ae399 --- /dev/null +++ b/kregexpeditor/multicontainerwidget.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "multicontainerwidget.h" +#include "dragaccepter.h" + +MultiContainerWidget::MultiContainerWidget( RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name) + :RegExpWidget( editorWindow, parent, name ) +{ +} + +void MultiContainerWidget::append( RegExpWidget* child ) +{ + child->reparent( this, QPoint(0,0), false ); + _children.append( child ); + _children.append( new DragAccepter( _editorWindow, this ) ); +} + +bool MultiContainerWidget::hasSelection() const +{ + if ( _isSelected ) + return true; + + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Move past the first dragAccepter + for ( ; *it; it += 2 ) { + if ( (*it)->hasSelection() ) { + return true; + } + } + return false; +} + +void MultiContainerWidget::clearSelection() +{ + _isSelected = false; + for ( unsigned int i = 0; i< _children.count(); i++ ) { + _children.at(i)->clearSelection(); + } +} + + +void MultiContainerWidget::deleteSelection() +{ + // run from the back to the front (which we do since we delete items on the run) + // When deleting children, delete the drag accepter to its right. + for ( int i = (int) _children.count()-2; i > 0; i -=2 ) { + + RegExpWidget* child = _children.at( i ); + if ( child->isSelected() ) { + delete _children.at( i+1 ); + _children.remove( i+1 ); + delete child; + _children.remove(i); + } + else if ( child->hasSelection() ) { + child->deleteSelection(); + } + } + _isSelected = false; + update(); +} + +void MultiContainerWidget::addNewChild(DragAccepter *accepter, RegExpWidget *child) +{ + for ( unsigned int i=0; i<_children.count(); i+= 2 ) { + RegExpWidget *ch = _children.at( i ); + if ( ch == accepter ) { + // Insert the new child + _children.insert( i+1, child ); + + // Insert an accepter as the next element. + DragAccepter *accepter = new DragAccepter( _editorWindow, this ); + + _children.insert( i+2, accepter ); + + // These two show's must come here otherwise a paintevent + // will be invoked, where the invariant, that a accepter is located at + // every second element. + child->show(); + accepter->show(); + + update(); + + return; + } + } + qFatal("Accepter not found in list"); +} + +bool MultiContainerWidget::updateSelection(bool parentSelected) +{ + bool changed = false; + bool isSel = _isSelected; + QMemArray<bool> oldState(_children.count()); + QMemArray<bool> newState(_children.count()); + + for (int i = 0; i< (int)_children.count();i++) { + oldState[i] = _children.at(i)->isSelected(); + } + + RegExpWidget::updateSelection( parentSelected ); + + int first; + int last; + + // scan for the first selected item. + for (first = 1; first < (int) _children.count(); first+= 2 ) { + RegExpWidget* child = _children.at(first); + changed = child->updateSelection( _isSelected ) || changed; + newState[first] = child->isSelected(); + if ( child->isSelected() ) + break; + } + + // scan for the last selected item + for (last = _children.count()-2; last>first; last -= 2) { + RegExpWidget* child = _children.at(last); + changed = child->updateSelection( _isSelected ) || changed; + newState[last] = child->isSelected(); + if ( child->isSelected() ) + break; + } + + // everything between first and last must be selected. + for (int j = first+2; j<last; j+=2) { + RegExpWidget* child = _children.at(j); + + changed = child->updateSelection( true ) || changed; + newState[j] = true; + } + + // update drag accepters. + for (int k = 0; k< (int) _children.count(); k+=2) { + RegExpWidget* child = _children.at(k); + bool select; + if ( k == 0 || k == (int)_children.count()-1) { + // The elements at the border is only selected if the parent is selected. + select = _isSelected; + } + else { + // Drag accepters in the middle is selected if the elements at both + // sides are selected. + select = newState[k-1] && newState[k+1]; + } + + bool isChildSel = child->isSelected(); + DragAccepter *accepter = dynamic_cast<DragAccepter*>(child); + if (accepter) + accepter->_isSelected = select; + if ( select != isChildSel ) + child->repaint(); + } + + changed = changed || isSel != _isSelected; + if ( changed ) { + repaint(); + } + + return changed; +} + + + +QRect MultiContainerWidget::selectionRect() const +{ + if ( _isSelected ) + return QRect( mapToGlobal( QPoint(0,0) ), size() ); + else { + QRect res; + QPtrListIterator<RegExpWidget> it(_children); + ++it; // Move past the first dragAccepter + for ( ; *it; it +=2 ) { + if ( (*it)->hasSelection() ) { + QRect childSel = (*it)->selectionRect(); + if ( res.isNull() ) + res = childSel; + else { + QRect newRes; + newRes.setLeft( QMIN( res.left(), childSel.left() ) ); + newRes.setTop( QMIN( res.top(), childSel.top() ) ); + newRes.setRight( QMAX( res.right(), childSel.right() ) ); + newRes.setBottom( QMAX( res.bottom(), childSel.bottom() ) ); + res = newRes; + } + } + } + return res; + } +} + +RegExpWidget* MultiContainerWidget::widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ) +{ + unsigned int start, incr; + if ( justVisibleWidgets ) { + start = 1; + incr = 2; + } + else { + start = 0; + incr = 1; + } + + for ( unsigned int i = start; i < _children.count(); i+=incr ) { + RegExpWidget* wid = _children.at(i)->widgetUnderPoint( globalPos, justVisibleWidgets ); + if ( wid ) + return wid; + } + if ( justVisibleWidgets ) + return 0; + else { + return RegExpWidget::widgetUnderPoint( globalPos, justVisibleWidgets ); + } +} + +RegExpWidget* MultiContainerWidget::findWidgetToEdit( QPoint globalPos ) +{ + for ( unsigned int i = 1; i < _children.count(); i+=2 ) { + RegExpWidget* wid = _children.at(i)->findWidgetToEdit( globalPos ); + if ( wid ) + return wid; + } + return 0; +} + +void MultiContainerWidget::selectWidget( bool sel ) +{ + RegExpWidget::selectWidget( sel ); + QPtrListIterator<RegExpWidget> it(_children); + for ( ; *it ; ++it ) { + (*it)->selectWidget( sel ); + } + update(); +} + +void MultiContainerWidget::updateAll() +{ + for ( QPtrListIterator<RegExpWidget> it(_children); *it ; ++it ) { + (*it)->updateAll(); + } + RegExpWidget::updateAll(); +} + +void MultiContainerWidget::updateCursorRecursively() +{ + for ( QPtrListIterator<RegExpWidget> it(_children); *it ; ++it ) { + (*it)->updateCursorRecursively(); + } + updateCursorShape(); +} diff --git a/kregexpeditor/multicontainerwidget.h b/kregexpeditor/multicontainerwidget.h new file mode 100644 index 0000000..3fa4095 --- /dev/null +++ b/kregexpeditor/multicontainerwidget.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __multicontainerwidget +#define __multicontainerwidget + +#include "regexpwidget.h" + +/** + Abstract RegExp widget class representing widgets having multible children. + @internal +*/ +class MultiContainerWidget :public RegExpWidget +{ +public: + MultiContainerWidget( RegExpEditorWindow* editorWindow, QWidget* parent = 0, + const char* name = 0); + virtual bool hasSelection() const; + virtual void clearSelection(); + virtual void deleteSelection(); + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + virtual bool updateSelection(bool parentSelected); + virtual QRect selectionRect() const; + virtual RegExpWidget* widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ); + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + virtual void selectWidget( bool sel ); + virtual void updateAll(); + virtual void updateCursorRecursively(); + +protected: + void append( RegExpWidget* child ); + QPtrList<RegExpWidget> _children; +}; + + +#endif // __multicontainerwidget diff --git a/kregexpeditor/myfontmetrics.cpp b/kregexpeditor/myfontmetrics.cpp new file mode 100644 index 0000000..cdf29b2 --- /dev/null +++ b/kregexpeditor/myfontmetrics.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "myfontmetrics.h" + +QSize HackCalculateFontSize(QFontMetrics fm, QString str ) +{ + QStringList list = QStringList::split( QString::fromLatin1("\n"), str ); + int maxWidth = 0; + int height = 0; + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + QSize size = fm.size( 0, *it ); + maxWidth = QMAX( maxWidth, size.width() ); + height += size.height(); + } + return QSize( maxWidth, height ); +} diff --git a/kregexpeditor/myfontmetrics.h b/kregexpeditor/myfontmetrics.h new file mode 100644 index 0000000..649d32b --- /dev/null +++ b/kregexpeditor/myfontmetrics.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __MYFONTMETRICS_H +#define __MYFONTMETRICS_H +#include <qfontmetrics.h> +#include <qstringlist.h> + +// QFontMetrics::size is broken, therefore I need this hack until it works in QT3 + +QSize HackCalculateFontSize(QFontMetrics fm, QString str ); + +#endif diff --git a/kregexpeditor/pair.h b/kregexpeditor/pair.h new file mode 100644 index 0000000..b7296c5 --- /dev/null +++ b/kregexpeditor/pair.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __pair_h +#define __pair_h + +/** + @internal +*/ +template<class F, class S> class Pair +{ +public: + Pair() {} + Pair(F first, S second) : _first(first), _second(second) {} + F first() { return _first; } + S second() { return _second; } +private: + F _first; + S _second; + +}; + +#endif // __pair_h diff --git a/kregexpeditor/picts/Makefile.am b/kregexpeditor/picts/Makefile.am new file mode 100644 index 0000000..32b5061 --- /dev/null +++ b/kregexpeditor/picts/Makefile.am @@ -0,0 +1,2 @@ +pics_DATA= altn.png begline.png compound.png neglookahead.png poslookahead.png select.png wordboundary.png anychar.png characters.png endline.png nonwordboundary.png repeat.png text.png error.png autoverify.png verify.png +picsdir = $(kde_datadir)/kregexpeditor/pics diff --git a/kregexpeditor/picts/altn.png b/kregexpeditor/picts/altn.png Binary files differnew file mode 100644 index 0000000..900a1e9 --- /dev/null +++ b/kregexpeditor/picts/altn.png diff --git a/kregexpeditor/picts/anychar.png b/kregexpeditor/picts/anychar.png Binary files differnew file mode 100644 index 0000000..11048ca --- /dev/null +++ b/kregexpeditor/picts/anychar.png diff --git a/kregexpeditor/picts/autoverify.png b/kregexpeditor/picts/autoverify.png Binary files differnew file mode 100644 index 0000000..af68612 --- /dev/null +++ b/kregexpeditor/picts/autoverify.png diff --git a/kregexpeditor/picts/begline.png b/kregexpeditor/picts/begline.png Binary files differnew file mode 100644 index 0000000..3465a9e --- /dev/null +++ b/kregexpeditor/picts/begline.png diff --git a/kregexpeditor/picts/characters.png b/kregexpeditor/picts/characters.png Binary files differnew file mode 100644 index 0000000..7f218bf --- /dev/null +++ b/kregexpeditor/picts/characters.png diff --git a/kregexpeditor/picts/compound.png b/kregexpeditor/picts/compound.png Binary files differnew file mode 100644 index 0000000..a56c9bb --- /dev/null +++ b/kregexpeditor/picts/compound.png diff --git a/kregexpeditor/picts/endline.png b/kregexpeditor/picts/endline.png Binary files differnew file mode 100644 index 0000000..29b512e --- /dev/null +++ b/kregexpeditor/picts/endline.png diff --git a/kregexpeditor/picts/error.png b/kregexpeditor/picts/error.png Binary files differnew file mode 100644 index 0000000..4738f60 --- /dev/null +++ b/kregexpeditor/picts/error.png diff --git a/kregexpeditor/picts/neglookahead.png b/kregexpeditor/picts/neglookahead.png Binary files differnew file mode 100644 index 0000000..3cc0291 --- /dev/null +++ b/kregexpeditor/picts/neglookahead.png diff --git a/kregexpeditor/picts/nonwordboundary.png b/kregexpeditor/picts/nonwordboundary.png Binary files differnew file mode 100644 index 0000000..b22f4d4 --- /dev/null +++ b/kregexpeditor/picts/nonwordboundary.png diff --git a/kregexpeditor/picts/poslookahead.png b/kregexpeditor/picts/poslookahead.png Binary files differnew file mode 100644 index 0000000..492692b --- /dev/null +++ b/kregexpeditor/picts/poslookahead.png diff --git a/kregexpeditor/picts/repeat.png b/kregexpeditor/picts/repeat.png Binary files differnew file mode 100644 index 0000000..2646111 --- /dev/null +++ b/kregexpeditor/picts/repeat.png diff --git a/kregexpeditor/picts/select.png b/kregexpeditor/picts/select.png Binary files differnew file mode 100644 index 0000000..e04ab17 --- /dev/null +++ b/kregexpeditor/picts/select.png diff --git a/kregexpeditor/picts/text.png b/kregexpeditor/picts/text.png Binary files differnew file mode 100644 index 0000000..8b256ca --- /dev/null +++ b/kregexpeditor/picts/text.png diff --git a/kregexpeditor/picts/verify.png b/kregexpeditor/picts/verify.png Binary files differnew file mode 100644 index 0000000..dd76b7c --- /dev/null +++ b/kregexpeditor/picts/verify.png diff --git a/kregexpeditor/picts/wordboundary.png b/kregexpeditor/picts/wordboundary.png Binary files differnew file mode 100644 index 0000000..0e89a6b --- /dev/null +++ b/kregexpeditor/picts/wordboundary.png diff --git a/kregexpeditor/positionregexp.cpp b/kregexpeditor/positionregexp.cpp new file mode 100644 index 0000000..df5311f --- /dev/null +++ b/kregexpeditor/positionregexp.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "positionregexp.h" +#include "errormap.h" + +PositionRegExp::PositionRegExp( bool selected, PositionType tp ) :RegExp( selected ) +{ + _tp = tp; +} + +bool PositionRegExp::check( ErrorMap& map, bool first , bool last ) +{ + if ( _tp == BEGLINE && !first) { + map.lineStartError(); + } + else if ( _tp == ENDLINE && !last ) { + map.lineEndError(); + } + return true; +} + +QDomNode PositionRegExp::toXml( QDomDocument* doc ) const +{ + switch (_tp) { + case BEGLINE: return doc->createElement(QString::fromLocal8Bit( "BegLine" ) ); + case ENDLINE: return doc->createElement(QString::fromLocal8Bit( "EndLine" ) ); + case WORDBOUNDARY: return doc->createElement(QString::fromLocal8Bit( "WordBoundary" ) ); + case NONWORDBOUNDARY: return doc->createElement(QString::fromLocal8Bit( "NonWordBoundary" ) ); + } + return QDomNode(); +} + +bool PositionRegExp::load( QDomElement /* top */, const QString& /*version*/ ) +{ + // Nothing to do. + return true; +} + diff --git a/kregexpeditor/positionregexp.h b/kregexpeditor/positionregexp.h new file mode 100644 index 0000000..db90f93 --- /dev/null +++ b/kregexpeditor/positionregexp.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __POSITIONREGEXP_H +#define __POSITIONREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `positions' regular expression + @internal +*/ +class PositionRegExp :public RegExp +{ +public: + enum PositionType { BEGLINE, ENDLINE, WORDBOUNDARY, NONWORDBOUNDARY }; + + PositionRegExp( bool selected, PositionType tp ); + PositionType position() const { return _tp; } + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return POSITION ;} + +private: + PositionType _tp; + +}; + +#endif // __POSITIONREGEXP_H diff --git a/kregexpeditor/predefined/General/Makefile.am b/kregexpeditor/predefined/General/Makefile.am new file mode 100644 index 0000000..338481b --- /dev/null +++ b/kregexpeditor/predefined/General/Makefile.am @@ -0,0 +1,5 @@ +pkg_DATA = spaces.regexp anything.regexp + +pkgdir = $(kde_datadir)/kregexpeditor/predefined/general + +EXTRA_DIST = $(pkg_DATA) diff --git a/kregexpeditor/predefined/General/anything.regexp b/kregexpeditor/predefined/General/anything.regexp new file mode 100644 index 0000000..d016906 --- /dev/null +++ b/kregexpeditor/predefined/General/anything.regexp @@ -0,0 +1,11 @@ +<?xml version="1.0" ?> +<!DOCTYPE RegularExpression PUBLIC "-//KDE//KRegexpEditor DTD 1.0//EN" "http://www.blackie.dk/kreg.dtd"> +<RegularExpression version="1.0" > + <Compound allowReplace="1" > + <Title>anything</Title> + <Description>This regular expression matches anything.</Description> + <Repeat lower="0" upper="-1" > + <AnyChar/> + </Repeat> + </Compound> +</RegularExpression> diff --git a/kregexpeditor/predefined/General/spaces.regexp b/kregexpeditor/predefined/General/spaces.regexp new file mode 100644 index 0000000..5bf8696 --- /dev/null +++ b/kregexpeditor/predefined/General/spaces.regexp @@ -0,0 +1,11 @@ +<?xml version="1.0" ?> +<!DOCTYPE RegularExpression PUBLIC "-//KDE//KRegexpEditor DTD 1.0//EN" "http://www.blackie.dk/kreg.dtd"> +<RegularExpression version="1.0" > + <Compound allowReplace="1" > + <Title>spaces</Title> + <Description>Matches an arbitrary amount of whitespace.</Description> + <Repeat lower="0" upper="-1" > + <TextRange space="1" /> + </Repeat> + </Compound> +</RegularExpression> diff --git a/kregexpeditor/predefined/Makefile.am b/kregexpeditor/predefined/Makefile.am new file mode 100644 index 0000000..05812f8 --- /dev/null +++ b/kregexpeditor/predefined/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=General diff --git a/kregexpeditor/predefined/README b/kregexpeditor/predefined/README new file mode 100644 index 0000000..7740948 --- /dev/null +++ b/kregexpeditor/predefined/README @@ -0,0 +1,2 @@ +This directory contains the predefined regular expressions. +Only one level of sub directories is supported. diff --git a/kregexpeditor/qregexpparser.l b/kregexpeditor/qregexpparser.l new file mode 100644 index 0000000..4fb90cc --- /dev/null +++ b/kregexpeditor/qregexpparser.l @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +%option noyywrap + +%{ + #include <qstring.h> + #include "textrangeregexp.h" + #include "gen_qregexpparser.hh" +#ifdef QT_ONLY + #include "compat.h" +#endif + void parseRange( char* txt, int* min, int* max ); + RegExp* parseCharClass( char* match ); +%} + +Escape \\. +BackRef \\[1-9][0-9]* +CharClass \[^?\]?[^]]*\] +Range \{[0-9]*(,[0-9]*)?\} +HexChar \\x[0-9a-fA-F]{1,4} +OctChar \\0[0-7]{1,4} +SpecialEsc \\[afnrtv] +%% +"\\b" return TOK_PosWordChar; +"\\B" return TOK_PosNonWordChar; +"\\d" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\D" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\s" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\S" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\w" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\W" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +{SpecialEsc} { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit( yytext ) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + +{HexChar} { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +{OctChar} { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"." return TOK_Dot; +"$" return TOK_Dollar; +"^" return TOK_Carat; +"(?:" return TOK_MagicLeftParent; +"(?=" return TOK_PosLookAhead; +"(?!" return TOK_NegLookAhead; +"(" return TOK_LeftParen; +")" return TOK_RightParent; +"|" return TOK_Bar; +"*" { qregexplval.range.min = 0; qregexplval.range.max=-1; return TOK_Quantifier; } +"?" { qregexplval.range.min = 0; qregexplval.range.max=1; return TOK_Quantifier; } +"+" { qregexplval.range.min = 1; qregexplval.range.max=-1; return TOK_Quantifier; } +{Range} { parseRange( yytext, &qregexplval.range.min, &qregexplval.range.max ); return TOK_Quantifier; } +{CharClass} { qregexplval.regexp = parseCharClass(yytext); return TOK_CharClass; } +{BackRef} { qregexplval.backRef = atoi( yytext+1 ); return TOK_BackRef; } +{Escape} { qregexplval.ch = yytext[1]; return TOK_EscapeChar; } +. { qregexplval.ch = yytext[0]; return TOK_Char; } + +%% + +void setParseData( QString qstr ) { + const char* cstr; + if ( qstr.isNull() ) + cstr = ""; + else + cstr = qstr.latin1(); + yy_switch_to_buffer( yy_scan_string( cstr ) ); +} + +/** + This function parses a range in a form similar to "{3,4}", "{,7}" + etc. and returns the value in the integers pointed to by min and max. +*/ +void parseRange( char* txt, int* min, int* max ) +{ + + /* + case txt min max + 1 {} 0 -1 + 2 {,} 0 -1 + 3 {5} 5 5 + 4 {5,} 5 -1 + 5 {,7} 0 7 + 6 {5,7} 5 7 + */ + char c; + int i = 1; + int minimum=0, maximum=0; + int minFound=0, maxFound=0, commaFound = 0; + + while ( (c = txt[i++]) != ',' && c != '}') { + minimum = minimum*10+ c-'0'; + minFound=1; + } + + if ( c == ',' ) + commaFound = 1; + + if ( c != '}' ) { + while ( (c = txt[i++]) != '}') { + maximum = maximum*10+ c-'0'; + maxFound = 1; + } + } + + *min = minimum; + if ( maxFound ) + *max = maximum; /* case 5,6 */ + else if ( !minFound ) + *max = -1; /* case 1,2 */ + else if ( commaFound ) + *max = -1; /* case 4 */ + else + *max = minimum; /* case 3 */ +} + + +/** + This function parses a character range like "[^ab1-4]". +*/ +RegExp* parseCharClass( char* match ) +{ + TextRangeRegExp* res = new TextRangeRegExp( false ); + QString txt = QString::fromLocal8Bit( match ); + txt = txt.mid(1,txt.length()-2); + + unsigned int i = 0; + QChar ch = txt.at(i++); + QString pendingChar; + QString thisChar; + bool charPending = false; + bool rangePending = false; + bool flushPending = false; + + if ( ch == QChar('^') ) { + res->setNegate( true ); + ch = txt.at(i++); + } + + do { + // If a character is pending, and the next char is '-' then we are + // possible looking at a range. + if ( ch == QChar('-') && charPending ) { + rangePending = true; + ch = txt.at(i++); + continue; + } + + // If we have a pending character, but do not also have a pending + // range, then the pending character was not part of a range, and + // should therefore just be added as a single character. + if ( charPending && !rangePending ) { + res->addCharacter( pendingChar ); + charPending = false; + } + + if ( ch == QChar('\\') ) { + // Handle the cases where an escape character is specified. + ch = txt.at(i++); + + if ( ch == QChar('a') || ch == QChar('f') || ch == QChar('n') || ch == QChar('r') || ch == QChar('t') || ch == QChar('v') ) { + // These are just seen as normal characters. + thisChar = QString::fromLocal8Bit("\\") + ch; + } + else if ( ch == QChar('d') ) { + // The following characters represent character groups. If any of + // these are seen in a range, then the range is ignored, thus [a-\s] + // matches an 'a', a '-', and a space (\s means space). + res->setDigit( true ); + flushPending = true; + } + else if ( ch == QChar('D') ) { + res->setNonDigit( true ); + flushPending = true; + } + else if ( ch == QChar('s') ) { + res->setSpace( true ); + flushPending = true; + } + else if ( ch == QChar('S') ) { + res->setNonSpace( true ); + flushPending = true; + } + else if ( ch == QChar('w') ) { + res->setWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('W') ) { + res->setNonWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('x') || ch == QChar('X') ) { + // This is a hexidecimal character: \xHHHH + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == 'a' || ch == 'A' || ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'd' || ch == 'D' || + ch == 'e' || ch == 'E' || ch == 'f' || ch == 'F' || + ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || + ch == '8' || ch == '9' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str; + } + else if ( ch == QChar('0') ) { + // This is an octal character + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str ; + } + else { + // Anything else escaped just means the character itself. + thisChar = ch; + } + } + else { + // A non escaped character. + thisChar = ch; + } + + // The characters \s,\S,\w,\W,\d or \D, can not be part of a range, + // thus if they are meet in what looks like a range, then the + // characters of the range is justed seen as normal non range + // characters. thus [a-\s] matches an 'a', a '-', and a space (\s means + // space). + if ( flushPending ) { + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + flushPending = false; + charPending = false; + rangePending = false; + } + else { + if ( rangePending ) { + res->addRange( pendingChar, thisChar ); + charPending = false; + rangePending = false; + } + else { + pendingChar = thisChar; + charPending = true; + } + } + ch = txt.at(i++); + } + while ( ch != QChar(']') && i <= txt.length() ); + + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + + return res; +} diff --git a/kregexpeditor/qregexpparser.y b/kregexpeditor/qregexpparser.y new file mode 100644 index 0000000..0faaf98 --- /dev/null +++ b/kregexpeditor/qregexpparser.y @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +%{ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kmessagebox.h> +#endif + + #include <qstring.h> + #include <stdlib.h> + + #include "regexp.h" + #include "textregexp.h" + #include "textrangeregexp.h" + #include "repeatregexp.h" + #include "lookaheadregexp.h" + #include "concregexp.h" + #include "altnregexp.h" + #include "positionregexp.h" + #include "dotregexp.h" + #include "compoundregexp.h" + + extern int yylex(); + extern void setParseData( QString str ); + int yyerror (const char *); + void setParseResult( RegExp* ); + RegExp* parseQtRegExp( QString qstr, bool* ok ); + static RegExp* parseResult; + static int _index; +%} + +%union { + struct { + int min; + int max; + } range; + int backRef; + RegExp* regexp; + char ch; +} + +%token TOK_Dot +%token TOK_Dollar +%token TOK_Carat +%token TOK_MagicLeftParent +%token TOK_PosLookAhead +%token TOK_NegLookAhead +%token TOK_LeftParen +%token TOK_RightParent +%token TOK_Bar +%token TOK_Quantifier +%token TOK_BackRef +%token TOK_CharClass +%token TOK_Char +%token TOK_EscapeChar +%token TOK_PosWordChar +%token TOK_PosNonWordChar + +%start regexp + +%% + +empty : /* nothing */ ; + +regexp : expression { setParseResult( $<regexp>1) ; } + | empty { setParseResult( new ConcRegExp( false ) ); } + ; + +expression : expression TOK_Bar term { + if ( dynamic_cast<AltnRegExp*>( $<regexp>1 ) ) { + $<regexp>$ = $<regexp>1; + } + else { + $<regexp>$ = new AltnRegExp( false ); + dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>1 ); + } + dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>3 ); + } + | term { $<regexp>$ = $<regexp>1; } + | expression TOK_Bar { + if ( dynamic_cast<AltnRegExp*>( $<regexp>1 ) ) { + $<regexp>$ = $<regexp>1; + } + else { + $<regexp>$ = new AltnRegExp( false ); + dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>1 ); + } + dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + } + | TOK_Bar term { + $<regexp>$ = new AltnRegExp( false ); + dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + dynamic_cast<AltnRegExp*>( $<regexp>$ )->addRegExp( $<regexp>2 ); + } + | TOK_Bar { $<regexp>$ = new AltnRegExp( false ); } + ; + +term : term factor { + RegExp* last = dynamic_cast<ConcRegExp*>( $<regexp>1 )->lastRegExp(); + TextRegExp *reg1, *reg2; + + if ( last && ( reg1 = dynamic_cast<TextRegExp*>( last ) ) && + ( reg2 = dynamic_cast<TextRegExp*>( $<regexp>2 ) ) ) { + reg1->append( reg2->text() ); + delete reg2; + } + else { + dynamic_cast<ConcRegExp*>($<regexp>$)->addRegExp( $<regexp>2 ); + } + $<regexp>$ = $<regexp>1; + } + | factor { + ConcRegExp* reg = new ConcRegExp( false ); + reg->addRegExp( $<regexp>1 ); + $<regexp>$ = reg; + } + ; + +factor : atom TOK_Quantifier { + $<regexp>$ = new RepeatRegExp( false, $<range>2.min, $<range>2.max, $<regexp>1 ); + } + | atom { $<regexp>$ = $<regexp>1; } + ; + +atom : TOK_LeftParen expression TOK_RightParent { + $<regexp>$ = $<regexp>2; + } + | TOK_MagicLeftParent expression TOK_RightParent { $<regexp>$ = $<regexp>2; } + | TOK_PosLookAhead expression TOK_RightParent { + $<regexp>$ = new LookAheadRegExp( false, LookAheadRegExp::POSITIVE, $<regexp>2 ); + } + | TOK_NegLookAhead expression TOK_RightParent { + $<regexp>$ = new LookAheadRegExp( false, LookAheadRegExp::NEGATIVE, $<regexp>2 ); + } + | TOK_CharClass { $<regexp>$ = $<regexp>1; } + | char { $<regexp>$ = $<regexp>1; } + | TOK_Dollar { $<regexp>$ = new PositionRegExp( false, PositionRegExp::ENDLINE ); } + | TOK_Carat { $<regexp>$ = new PositionRegExp( false, PositionRegExp::BEGLINE ); } + | TOK_Dot { $<regexp>$ = new DotRegExp( false ); } + | TOK_BackRef { + QString match = QString::fromLocal8Bit("\\%1").arg( $<backRef>1 ); + $<regexp>$ = new TextRegExp( false, match ); + KMessageBox::information(0,i18n("<qt>Back reference regular expressions are not supported.<p>" + "<tt>\\1</tt>, <tt>\\2</tt>, ... are <i>back references</i>, meaning they refer to " + "previous matches. " + "Unfortunately this is not supported in the current version of this editor.<p>" + "In the graphical area the text <b>%1</b> has been inserted. This is however " + "just a workaround to ensure that the application handles the regexp at all. " + "Therefore, as soon as you edit the regular expression in the graphical area, " + "the back reference will be replaced by matching the text <b>%2</b> literally.") + .arg( match ).arg( match ), + i18n("Back reference regular expressions not supported"), + QString::fromLocal8Bit("backReferenceNotSupported") ); + } + | TOK_PosWordChar { $<regexp>$ = new PositionRegExp( false, PositionRegExp::WORDBOUNDARY ); } + | TOK_PosNonWordChar { $<regexp>$ = new PositionRegExp( false, PositionRegExp::NONWORDBOUNDARY ); } + ; + +char : TOK_Char { + if ( $<ch>1 == '{' || $<ch>1 == '}' || $<ch>1 == '[' || $<ch>1 == ']' || $<ch>1 == '\\' ) { + yyerror( "illigal character - needs escaping" ); + } + $<regexp>$ = new TextRegExp( false, QString::fromLocal8Bit("%1").arg($<ch>1)); + } + | TOK_EscapeChar { $<regexp>$ = new TextRegExp( false, QString::fromLocal8Bit("%1").arg($<ch>1)); } + ; + +%% + +RegExp* parseQtRegExp( QString qstr, bool* ok ) { + _index = 0; + parseResult = 0; + setParseData( qstr ); + yyparse(); + *ok = ( yynerrs == 0 ); + return parseResult; +} + +void setParseResult( RegExp* regexp ) { + parseResult = regexp; +} + +int yyerror(const char *) { + yynerrs++; + return 0; +} diff --git a/kregexpeditor/qt-only/clean b/kregexpeditor/qt-only/clean new file mode 100755 index 0000000..57e9a6d --- /dev/null +++ b/kregexpeditor/qt-only/clean @@ -0,0 +1,14 @@ +#!/bin/sh +rm *.o +rm *.obj +rm -rf manual +rm -rf predefined +rm -rf icons +rm unistd.h +find -lname \* -maxdepth 1 | xargs rm +rm moc_* +rm images.h +rm gen_* +rm -rf kregexpeditor* +rm Makefile +rm kregexpeditor.zip diff --git a/kregexpeditor/qt-only/compat.cpp b/kregexpeditor/qt-only/compat.cpp new file mode 100644 index 0000000..7dbc7b4 --- /dev/null +++ b/kregexpeditor/qt-only/compat.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "compat.h" + +QString i18n( const QString& a) { + return QObject::tr(a); +} + +QString i18n( const QString& a, const QString& b) { + return QObject::tr(b,a); +} + +KDialogBase::KDialogBase( int /*dialogFace*/, const QString &caption, int buttonMask, + ButtonCode defaultButton, QWidget *parent, const char *name, + bool modal ) + :QDialog( parent, name, modal ) +{ + init( buttonMask, defaultButton, caption ); +} + +KDialogBase::KDialogBase( QWidget* parent, const char* name, bool modal, + const QString& caption, int buttonMask ) + : QDialog( parent, name, modal ) +{ + init( buttonMask, Ok, caption ); +} + +void KDialogBase::init( int buttonMask, ButtonCode /*defaultButton*/, const QString& caption ) +{ + setCaption( caption ); + _layout = new QVBoxLayout( this, 6 ); + QHBoxLayout* buts = new QHBoxLayout( _layout, 6 ); + QPushButton* but; + if ( buttonMask & Help ) { + but = new QPushButton( tr("Help"), this ); + buts->addWidget( but ); + connect( but, SIGNAL( clicked() ), this, SIGNAL( helpClicked() ) ); + } + buts->addStretch(1); + if ( buttonMask & Ok ) { + but = new QPushButton( tr("OK"), this ); + buts->addWidget( but ); + connect( but, SIGNAL( clicked() ), this, SLOT( slotOk() ) ); + } + if ( buttonMask & Cancel ) { + but = new QPushButton( tr("Cancel"), this ); + buts->addWidget( but ); + connect( but, SIGNAL( clicked() ), this, SLOT( slotCancel() ) ); + } +} + +void KDialogBase::setMainWidget( QWidget* top ) +{ + top->reparent( this, 0, QPoint(0,0) ); + _layout->insertWidget( 0, top ); +} + +QFrame* KDialogBase::plainPage() +{ + QFrame* frame = new QFrame( this ); + setMainWidget( frame ); + return frame; +} + +void KDialogBase::slotOk() +{ + accept(); + emit okClicked(); + emit finished(); +} + +void KDialogBase::slotCancel() +{ + reject(); + emit cancelClicked(); + emit finished(); +} + +int KMessageBox::warningYesNo(QWidget *parent, const QString &text, const QString &caption ) +{ + int code = warning( parent, caption, text, tr("No"), tr("Yes") ); + if ( code == 0 ) + return Yes; + else + return No; +} + +int KMessageBox::information( QWidget* parent, const QString& text, const QString& caption, + const QString& /*dontShowAgainName*/ ) +{ + return QMessageBox::information( parent, caption, text ); +} + +int KMessageBox::sorry( QWidget* parent, const QString& text, const QString& caption ) +{ + return QMessageBox::information( parent, caption, text ); +} + + diff --git a/kregexpeditor/qt-only/compat.h b/kregexpeditor/qt-only/compat.h new file mode 100644 index 0000000..edf9ced --- /dev/null +++ b/kregexpeditor/qt-only/compat.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef COMPAT_H +#define COMPAT_H +#include <qobject.h> +#include <qmessagebox.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qinputdialog.h> +#include <qframe.h> + +QString i18n( const QString& a); +QString i18n( const QString& a, const QString& b); +#define isatty(x) 0 + +#define KTextBrowser QTextBrowser +#define KListBox QListBox +#define KFileDialog QFileDialog +#define KPushButton QPushButton + +class KDialogBase :public QDialog +{ + Q_OBJECT + +public: + enum ButtonCode {Ok = 1, Cancel, Help}; + enum DialogType { Plain }; + + KDialogBase ( int dialogFace, const QString &caption, int buttonMask, + ButtonCode defaultButton, + QWidget *parent=0, const char *name=0, bool modal=true ); + + KDialogBase( QWidget* parent, const char* name = 0, bool modal = true, + const QString& caption = QString::null, + int buttonMask = 0 ); + + void init( int buttonMask, ButtonCode /*defaultButton*/, const QString& caption ); + void setMainWidget( QWidget* top ); + QFrame* plainPage(); + void setHelp( const QString&, const QString& ) {} + +public slots: + void slotOk(); + void slotCancel(); + +signals: + void okClicked(); + void cancelClicked(); + void finished(); + void helpClicked(); + +private: + QVBoxLayout* _layout; +}; + +class KMessageBox :public QMessageBox +{ + Q_OBJECT +public: + enum ButtonCode { Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 }; + static int warningYesNo (QWidget *parent, const QString &text, + const QString &caption = QString::null ); + static int information( QWidget* parent, const QString& text, const QString& caption = QString::null, + const QString& /*dontShowAgainName*/ = QString::null ); + static int sorry( QWidget* parent, const QString& text, const QString& caption = QString::null ); +}; + +#endif /* COMPAT_H */ + diff --git a/kregexpeditor/qt-only/compile b/kregexpeditor/qt-only/compile new file mode 100755 index 0000000..d6fb6c6 --- /dev/null +++ b/kregexpeditor/qt-only/compile @@ -0,0 +1,28 @@ +#!/bin/bash +# On Linux do this +ln -s ../*.{cpp,h,y,l} . +ln -s ../{KMultiFormListBox,KWidgetStreamer}/*.{cpp,h} . +ln -s $KDESRC/kdelibs/interfaces/kregexpeditor/kregexpeditorinterface.h . +ln -s gen_qregexpparser.cc gen_qregexpparser.cpp +touch unistd.h +mkdir icons +cp ../picts/* icons +cp $KDEDIR/share/icons/crystalsvg/22x22/actions/{undo,redo,editcut,editcopy,editpaste,fileopen,filesave,contexthelp,1downarrow,1uparrow}.png icons +mkdir predefined +mkdir predefined/General +cp ../predefined/General/*.regexp predefined/General + +flex -Pqregexp -ogen_qregexplexer.cpp qregexpparser.l +bison -d -p qregexp -o gen_qregexpparser.cc qregexpparser.y + +mkdir manual +cd manual +meinproc $KDESRC/kdeutils/doc/KRegExpEditor/index.docbook +for x in *.html; do sed 's/<img src="help:[^>]*>//' < $x > tmp.html; mv tmp.html $x; done +cp $KDESRC/kdeutils/doc/KRegExpEditor/*.png . +cd .. +(cd icons; $QTDIR/tools/qembed/qembed --images *.png > ../images.h) + +# Now on windows do the following +qmake +make diff --git a/kregexpeditor/qt-only/qt-only.pro b/kregexpeditor/qt-only/qt-only.pro new file mode 100644 index 0000000..9af8b97 --- /dev/null +++ b/kregexpeditor/qt-only/qt-only.pro @@ -0,0 +1,137 @@ +TEMPLATE = app +INCLUDEPATH += . +DEFINES += QT_ONLY +TARGET = kregexpeditor + +win32-msvc:QMAKE_CXXFLAGS += /GX /GR +QMAKE_CLEAN+=vc60.pdb kdexecutor.dsp + + +# If this is a compile for House Of Fusion, then add the following line +DEFINES+=HOUSEOFFUSION + +# Input +HEADERS += altnregexp.h \ + altnwidget.h \ + auxbuttons.h \ + ccp.h \ + characterswidget.h \ + charselector.h \ + compoundregexp.h \ + compoundwidget.h \ + concregexp.h \ + concwidget.h \ + dcbutton.h \ + dotregexp.h \ + drag.h \ + dragaccepter.h \ + editorwindow.h \ + emacsregexpconverter.h \ + errormap.h \ + gen_qregexpparser.hh \ + indexWindow.h \ + infopage.h \ + kmultiformlistbox-multivisible.h \ + kmultiformlistbox-shower.h \ + kmultiformlistbox-windowed.h \ + kmultiformlistbox.h \ + kmultiformlistboxentry.h \ + kmultiformlistboxfactory.h \ + kregexpeditorgui.h \ + kregexpeditorprivate.h \ + kwidgetstreamer.h \ + limitedcharlineedit.h \ + lookaheadregexp.h \ + lookaheadwidget.h \ + multicontainerwidget.h \ + myfontmetrics.h \ + pair.h \ + positionregexp.h \ + qtregexpconverter.h \ + qtregexphighlighter.h \ + regexp.h \ + regexpbuttons.h \ + regexpconverter.h \ + regexphighlighter.h \ + regexpwidget.h \ + repeatregexp.h \ + repeatwidget.h \ + scrollededitorwindow.h \ + selectablelineedit.h \ + singlecontainerwidget.h \ + textrangeregexp.h \ + textregexp.h \ + textwidget.h \ + triple.h \ + userdefinedregexps.h \ + verifier.h \ + verifybuttons.h \ + widgetfactory.h \ + widgetwindow.h \ + windowlistboxitem.h \ + zerowidgets.h\ + compat.h \ + images.h + +#LEXSOURCES += qregexpparser.l +#YACCSOURCES += qregexpparser.y +YACC=bison +SOURCES += altnregexp.cpp \ + altnwidget.cpp \ + auxbuttons.cpp \ + ccp.cpp \ + characterswidget.cpp \ + charselector.cpp \ + compoundregexp.cpp \ + compoundwidget.cpp \ + concregexp.cpp \ + concwidget.cpp \ + dcbutton.cpp \ + dotregexp.cpp \ + drag.cpp \ + dragaccepter.cpp \ + editorwindow.cpp \ + emacsregexpconverter.cpp \ + errormap.cpp \ + gen_qregexplexer.cpp \ + indexWindow.cpp \ + infopage.cpp \ + kmultiformlistbox-multivisible.cpp \ + kmultiformlistbox-windowed.cpp \ + kmultiformlistbox.cpp \ + kmultiformlistboxentry.cpp \ + kmultiformlistboxfactory.cpp \ + kregexpeditorgui.cpp \ + kregexpeditorprivate.cpp \ + kwidgetstreamer.cpp \ + limitedcharlineedit.cpp \ + lookaheadregexp.cpp \ + lookaheadwidget.cpp \ + main.cpp \ + multicontainerwidget.cpp \ + myfontmetrics.cpp \ + positionregexp.cpp \ + qtregexpconverter.cpp \ + qtregexphighlighter.cpp \ + regexp.cpp \ + regexpbuttons.cpp \ + regexpconverter.cpp \ + regexphighlighter.cpp \ + regexpwidget.cpp \ + repeatregexp.cpp \ + repeatwidget.cpp \ + scrollededitorwindow.cpp \ + selectablelineedit.cpp \ + singlecontainerwidget.cpp \ + textrangeregexp.cpp \ + textregexp.cpp \ + textwidget.cpp \ + userdefinedregexps.cpp \ + verifier.cpp \ + verifybuttons.cpp \ + widgetfactory.cpp \ + widgetwindow.cpp \ + windowlistboxitem.cpp \ + zerowidgets.cpp \ + gen_qregexpparser.cpp \ + compat.cpp diff --git a/kregexpeditor/qt-only/win-release.bat b/kregexpeditor/qt-only/win-release.bat new file mode 100644 index 0000000..967afc8 --- /dev/null +++ b/kregexpeditor/qt-only/win-release.bat @@ -0,0 +1,7 @@ +md kregexpeditor +cp -r kregexpeditor.exe predefined kregexpeditor +copy q:\3.1.2-mt\lib\qt-mt312.dll kregexpeditor +copy c:\winnt\system32\MSVCRTD.DLL kregexpeditor +copy c:\winnt\system32\MSVCP60D.DLL kregexpeditor +cp -r manual kregexpeditor +c:\zip\zip -r kregexpeditor.zip kregexpeditor diff --git a/kregexpeditor/qtregexpconverter.cpp b/kregexpeditor/qtregexpconverter.cpp new file mode 100644 index 0000000..198d7dd --- /dev/null +++ b/kregexpeditor/qtregexpconverter.cpp @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "qtregexpconverter.h" +#include "qtregexphighlighter.h" +#include "regexp.h" +#include "textregexp.h" +#include "altnregexp.h" +#include "concregexp.h" +#include "lookaheadregexp.h" +#include "textrangeregexp.h" +#include "compoundregexp.h" +#include "dotregexp.h" +#include "positionregexp.h" +#include "repeatregexp.h" + +extern RegExp* parseQtRegExp( QString str, bool *ok ); +extern RegExp* parseDataQtRegExp(); + +bool QtRegExpConverter::canParse() +{ + return true; +} + + +RegExp* QtRegExpConverter::parse( const QString& txt, bool* ok ) +{ + return parseQtRegExp( txt, ok ); +} + +QString QtRegExpConverter::toString( AltnRegExp* regexp, bool markSelection ) +{ + QString res; + + bool first = true; + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + if ( !first ) { + res += QString::fromLatin1( "|" ); + } + first = false; + if ( markSelection && !regexp->isSelected() && (*it)->isSelected() ) { + res += QString::fromLatin1("(") + toStr( *it, markSelection ) + QString::fromLatin1(")"); + } + else { + res += toStr( *it, markSelection ); + } + } + return res; +} + +QString QtRegExpConverter::toString( ConcRegExp* regexp, bool markSelection ) +{ + QString res; + bool childSelected = false; + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + QString startPar = QString::fromLocal8Bit(""); + QString endPar = QString::fromLocal8Bit(""); + if ( (*it)->precedence() < regexp->precedence() ) { + if ( markSelection ) + startPar = QString::fromLocal8Bit("(?:"); + else + startPar = QString::fromLatin1( "(" ); + endPar = QString::fromLatin1( ")" ); + } + + // Note these two have different tests! They are activated in each their iteration of the loop. + if ( markSelection && !childSelected && !regexp->isSelected() && (*it)->isSelected() ) { + res += QString::fromLatin1("("); + childSelected = true; + } + + if ( markSelection && childSelected && !regexp->isSelected() && !(*it)->isSelected() ) { + res += QString::fromLatin1(")"); + childSelected= false; + } + + res += startPar + toStr( *it, markSelection ) + endPar; + } + if ( markSelection && childSelected && !regexp->isSelected() ) { + res += QString::fromLatin1(")"); + } + return res; +} + +QString QtRegExpConverter::toString( LookAheadRegExp* regexp, bool markSelection ) +{ + if ( regexp->lookAheadType() == LookAheadRegExp::POSITIVE ) + return QString::fromLatin1( "(?=" ) + toStr( regexp->child(), markSelection ) + QString::fromLocal8Bit( ")" ); + else + return QString::fromLatin1( "(?!" ) + toStr( regexp->child(), markSelection ) + QString::fromLocal8Bit( ")" ); +} + +QString QtRegExpConverter::toString( TextRangeRegExp* regexp, bool /*markSelection*/ ) +{ + QString txt; + + bool foundCarrot = false; + bool foundDash = false; + bool foundParenthesis = false; + + // Now print the rest of the single characters, but keep "^" as the very + // last element of the characters. + QStringList chars = regexp->chars(); + for (unsigned int i = 0; i< chars.count(); i++) { + if ( *chars.at(i) == QChar( ']' ) ) { + foundParenthesis = true; + } + else if ( *chars.at(i) == QChar( '-' ) ) { + foundDash = true; + } + else if ( *chars.at(i) == QChar( '^' ) ) { + foundCarrot = true; + } + else { + txt.append( *chars.at(i) ); + } + } + + // Now insert the ranges. + QPtrList<StringPair> ranges = regexp->range(); + for ( QPtrListIterator<StringPair> it(ranges); *it; ++it ) { + txt.append((*it)->first()+ QString::fromLatin1("-")+ (*it)->second()); + } + + // Ok, its time to build each part of the regexp, here comes the rule: + // if a ']' is one of the characters, then it must be the first one in the + // list (after then opening '[' and eventually negation '^') + // Next if a '-' is one of the characters, then it must come + // finally if '^' is one of the characters, then it must not be the first + // one! + + QString res = QString::fromLatin1("["); + + if ( regexp->negate() ) + res.append(QString::fromLatin1("^")); + + + // a ']' must be the first character in teh range. + if ( foundParenthesis ) { + res.append(QString::fromLatin1("]")); + } + + // a '-' must be the first character ( only coming after a ']') + if ( foundDash ) { + res.append(QString::fromLatin1("-")); + } + + res += txt; + + // Insert \s,\S,\d,\D,\w, and \W + if ( regexp->digit() ) + res += QString::fromLocal8Bit("\\d"); + if ( regexp->nonDigit() ) + res += QString::fromLocal8Bit("\\D"); + if ( regexp->space() ) + res += QString::fromLocal8Bit("\\s"); + if ( regexp->nonSpace() ) + res += QString::fromLocal8Bit("\\S"); + if ( regexp->wordChar() ) + res += QString::fromLocal8Bit("\\w"); + if ( regexp->nonWordChar() ) + res += QString::fromLocal8Bit("\\W"); + + + if ( foundCarrot ) { + res.append( QChar( '^' ) ); + } + + res.append(QString::fromLatin1("]")); + + return res; +} + +QString QtRegExpConverter::toString( CompoundRegExp* regexp, bool markSelection ) +{ + if ( markSelection && !regexp->isSelected() && regexp->child()->isSelected() ) + return QString::fromLatin1( "(" ) + toStr( regexp->child(), markSelection ) + QString::fromLatin1( ")" ); + else + return toStr( regexp->child(), markSelection ); +} + +QString QtRegExpConverter::toString( DotRegExp* /*regexp*/, bool /*markSelection*/ ) +{ + return QString::fromLatin1( "." ); +} + +QString QtRegExpConverter::toString( PositionRegExp* regexp, bool /*markSelection*/ ) +{ + switch (regexp->position()) { + case PositionRegExp::BEGLINE: + return QString::fromLatin1("^"); + case PositionRegExp::ENDLINE: + return QString::fromLatin1("$"); + case PositionRegExp::WORDBOUNDARY: + return QString::fromLatin1("\\b"); + case PositionRegExp::NONWORDBOUNDARY: + return QString::fromLatin1("\\B"); + } + Q_ASSERT( false ); + return QString::fromLatin1(""); +} + +QString QtRegExpConverter::toString( RepeatRegExp* regexp, bool markSelection ) +{ + RegExp* child = regexp->child(); + QString cText = toStr( child, markSelection ); + QString startPar; + QString endPar; + + if ( markSelection ) { + if ( !regexp->isSelected() && child->isSelected()) { + startPar = QString::fromLatin1( "(" ); + endPar = QString::fromLatin1( ")" ); + } + else if ( child->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "(?:" ); + endPar = QString::fromLatin1( ")" ); + } + } + else if ( child->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "(" ); + endPar = QString::fromLatin1( ")" ); + } + + if ( regexp->min() == 0 && regexp->max() == -1) { + return startPar + cText +endPar + QString::fromLocal8Bit("*"); + } + else if ( regexp->min() == 0 && regexp->max() == 1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("?"); + } + else if ( regexp->min() == 1 && regexp->max() == -1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("+"); + } + else if ( regexp->max() == -1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("{") + + QString::number( regexp->min() ) + QString::fromLocal8Bit(",") + + QString::fromLocal8Bit("}"); + } + else { + return startPar + cText + endPar + QString::fromLocal8Bit("{") + + QString::number( regexp->min() ) + QString::fromLocal8Bit(",") + + QString::number( regexp->max() ) + QString::fromLocal8Bit("}"); + } +} + +QString QtRegExpConverter::toString( TextRegExp* regexp, bool /*markSelection*/ ) +{ + QValueList<QChar> list; + list << QChar('$') + << QChar('^') + << QChar('.') + << QChar('*') + << QChar('+') + << QChar('?') + << QChar('[') + << QChar(']') + << QChar('\\') + << QChar('{') + << QChar('}') + << QChar('(') + << QChar(')') + << QChar('|'); + + QString res = escape( regexp->text(), list, QChar('\\') ); + return res; +} + +QString QtRegExpConverter::name() +{ + return QString::fromLatin1( "Qt" ); +} + +int QtRegExpConverter::features() +{ + return WordBoundary | NonWordBoundary | PosLookAhead | NegLookAhead | CharacterRangeNonItems | ExtRange; +} + +RegexpHighlighter* QtRegExpConverter::highlighter( QTextEdit* edit ) +{ + return new QtRegexpHighlighter( edit ); +} diff --git a/kregexpeditor/qtregexpconverter.h b/kregexpeditor/qtregexpconverter.h new file mode 100644 index 0000000..100dcf3 --- /dev/null +++ b/kregexpeditor/qtregexpconverter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QTREGEXPCONVERTER_H +#define QTREGEXPCONVERTER_H +#include "regexpconverter.h" + +class QtRegExpConverter :public RegExpConverter +{ +public: + virtual bool canParse(); + virtual RegExp* parse( const QString&, bool* ok ); + virtual QString name(); + virtual int features(); + virtual QString toString( AltnRegExp*, bool markSelection ); + virtual QString toString( ConcRegExp*, bool markSelection ); + virtual QString toString( LookAheadRegExp*, bool markSelection ); + virtual QString toString( TextRangeRegExp*, bool markSelection ); + virtual QString toString( CompoundRegExp*, bool markSelection ); + virtual QString toString( DotRegExp*, bool markSelection ); + virtual QString toString( PositionRegExp*, bool markSelection ); + virtual QString toString( RepeatRegExp*, bool markSelection ); + virtual QString toString( TextRegExp*, bool markSelection ); + RegexpHighlighter* highlighter( QTextEdit* edit ); +}; + +#endif /* QTREGEXPCONVERTER_H */ + diff --git a/kregexpeditor/qtregexphighlighter.cpp b/kregexpeditor/qtregexphighlighter.cpp new file mode 100644 index 0000000..1983b89 --- /dev/null +++ b/kregexpeditor/qtregexphighlighter.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "qtregexphighlighter.h" +#include <qregexp.h> +QtRegexpHighlighter::QtRegexpHighlighter( QTextEdit* editor ) + :RegexpHighlighter( editor ), _editor( editor ) +{ +} + +int QtRegexpHighlighter::highlightParagraph( const QString & text, int endStateOfLastPara ) +{ + QRegExp regexp( _regexp ); + regexp.setCaseSensitive( _caseSensitive ); + regexp.setMinimal( _minimal ); + + setFormat( 0, text.length(), _editor->font(), Qt::black ); + + if ( !regexp.isValid() || regexp.isEmpty() ) { + return 0; + } + + // ------------------------------ Process with the regular expression. + QColor colors[] = { Qt::red, Qt::blue }; + int color = endStateOfLastPara; + if ( color < 0 || color > 1 ) + color = 0; + + int index = 0; + int start, length; + while ( (index = regexp.search( text, index ) ) != -1 && index < (int) text.length()) { + if ( regexp.pos(1) != -1 ) { + start = regexp.pos(1); + length = regexp.cap(1).length(); + } + else { + start = index; + length = regexp.matchedLength(); + } + + if ( start != index ) + setFormat( index, start-index, colors[color] ); + + QFont font = _editor->font(); + font.setUnderline( true ); + font.setPointSize( (int) (font.pointSize() * 1.3) ); + setFormat( start, length, font, colors[color] ); + + if ( length + (start-index) != regexp.matchedLength() ) + setFormat( start+length, regexp.matchedLength()-length-(start-index), colors[color] ); + + index += QMAX( 1, regexp.matchedLength() ); // ensure progress when matching for example ^ or \b + color = (color+1)%2; + } + return color; +} + diff --git a/kregexpeditor/qtregexphighlighter.h b/kregexpeditor/qtregexphighlighter.h new file mode 100644 index 0000000..bb57bda --- /dev/null +++ b/kregexpeditor/qtregexphighlighter.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QTREGEXPHIGHLIGHTER_H +#define QTREGEXPHIGHLIGHTER_H +#include "regexphighlighter.h" +#include <qtextedit.h> + +class QtRegexpHighlighter :public RegexpHighlighter +{ +public: + QtRegexpHighlighter( QTextEdit* verifier ); + virtual int highlightParagraph ( const QString & text, int endStateOfLastPara ); + +private: + QTextEdit* _editor; +}; + +#endif /* QTREGEXPHIGHLIGHTER_H */ + diff --git a/kregexpeditor/regexp.cpp b/kregexpeditor/regexp.cpp new file mode 100644 index 0000000..31450f1 --- /dev/null +++ b/kregexpeditor/regexp.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "regexp.h" +#include "widgetfactory.h" +#include "kregexpeditorgui.h" +#include "errormap.h" + +RegExp::RegExp( bool selected ) : _parent(0), _destructing( false ), _selected( selected ) +{ + // Nothing to do +} + +RegExp::~RegExp() +{ + _destructing = true; + for ( QPtrListIterator<RegExp> it(_children); *it; ++it ) { + delete *it; + } + if ( _parent ) + _parent->removeChild( this ); + _parent = 0; +} + +void RegExp::addChild( RegExp* child ) +{ + _children.append( child ); + child->setParent( this ); +} + +void RegExp::removeChild( RegExp* child ) +{ + if ( ! _destructing ) { + _children.remove( child ); + } +} + +void RegExp::setParent( RegExp* parent ) +{ + _parent = parent; +} + +RegExp* RegExp::readRegExp( QDomElement top, const QString& version ) +{ + for ( QDomNode node = top.firstChild(); !node.isNull(); node = node.nextSibling() ) { + if (!node.isElement() ) + continue; // skip past comments + RegExp* regexp = WidgetFactory::createRegExp(node.toElement(), version ); + return regexp; + } + return 0; +} + +QString RegExp::toXmlString() const +{ + QDomDocument doc; + doc.setContent( QString::fromLatin1( "<RegularExpression/>" ) ); + QDomNode top = doc.documentElement(); + top.toElement().setAttribute(QString::fromLocal8Bit("version"), KRegExpEditorGUI::version); + + QDomNode elm = toXml( &doc ); + + top.appendChild( elm ); + QString xmlString = QString::fromLocal8Bit("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE RegularExpression PUBLIC \"-//KDE//KRegexpEditor DTD 1.0//EN\" \"http://www.blackie.dk/kreg.dtd\">\n") + doc.toString(); + + return xmlString; +} + +RegExp* RegExp::clone() const +{ + return WidgetFactory::createRegExp( toXmlString() ); +} + +void RegExp::check( ErrorMap& map ) +{ + map.start(); + check( map, true, true ); + map.end(); +} + + diff --git a/kregexpeditor/regexp.h b/kregexpeditor/regexp.h new file mode 100644 index 0000000..86bd796 --- /dev/null +++ b/kregexpeditor/regexp.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef REGEXP_H +#define REGEXP_H + +#include <qdom.h> +#include <qptrlist.h> + +class CompoundRegExp; +class ErrorMap; + +/** + Abstract syntax tree for regular expressions. + @internal +*/ +class RegExp +{ +public: + RegExp( bool selected ); + virtual ~RegExp(); + + virtual int precedence() const = 0; + virtual QDomNode toXml( QDomDocument* doc ) const = 0; + virtual bool load( QDomElement, const QString& version ) = 0; + QString toXmlString() const; + + void check( ErrorMap& ); + virtual bool check( ErrorMap&, bool first, bool last ) = 0; + + void addChild( RegExp* child ); + void removeChild( RegExp* child ); + void setParent( RegExp* parent ); + RegExp* clone() const; + virtual bool operator==( const RegExp& other ) const { return ( type() == other.type() ); } + + enum RegExpType { CONC, TEXT, DOT, POSITION, REPEAT, ALTN, COMPOUND, LOOKAHEAD, TEXTRANGE }; + virtual RegExpType type() const = 0; + virtual void replacePart( CompoundRegExp* /* replacement */ ) {} + bool isSelected() const { return _selected; } + void setSelected( bool b ) { _selected = b; } + +protected: + RegExp* readRegExp( QDomElement top, const QString& version ); + +private: + RegExp() {} // disable + QPtrList<RegExp> _children; + RegExp* _parent; + bool _destructing; + bool _selected; +}; + +typedef QPtrList<RegExp> RegExpList; +typedef QPtrListIterator<RegExp> RegExpListIt; + +#endif // REGEXP_H + diff --git a/kregexpeditor/regexpbuttons.cpp b/kregexpeditor/regexpbuttons.cpp new file mode 100644 index 0000000..eae7da0 --- /dev/null +++ b/kregexpeditor/regexpbuttons.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include <kiconloader.h> + #include <klocale.h> + #include <kstandarddirs.h> + #include "regexpbuttons.moc" +#endif + +#include "regexpbuttons.h" +#include "dcbutton.h" +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qbuttongroup.h> +#include <qlayout.h> +#include <qsignalmapper.h> +#include "regexpconverter.h" + +RegExpButtons::RegExpButtons( QWidget *parent, const char *name ) + : QDockWindow( QDockWindow::InDock, parent, name), _keepMode(false) +{ + QBoxLayout *layout = boxLayout(); + + _grp = new QButtonGroup(this); + _grp->hide(); + _grp->setExclusive( true ); + + _mapper = new QSignalMapper( this, "RegExpButtons::_mapper" ); + connect( _mapper, SIGNAL( mapped(int) ), this, SIGNAL( clicked(int) ) ); + + // The "select" button. + _selectBut = new QToolButton( this); + +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( "select" ) ); +#else + QPixmap pix = KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/select.png") ), KIcon::Toolbar ); +#endif + + _selectBut->setPixmap( pix ); + layout->addWidget( _selectBut ); + _grp->insert(_selectBut); + _selectBut->setToggleButton( true ); + connect( _selectBut, SIGNAL(clicked()), SIGNAL(doSelect())); + connect( _selectBut, SIGNAL(clicked()), this, SLOT(slotSetNonKeepMode()) ); + + QToolTip::add( _selectBut, i18n("Selection tool")); + QWhatsThis::add( _selectBut, i18n("<qt>This will change the state of the editor to <i>selection state</i>.<p>" + "In this state you will not be inserting <i>regexp items</i>, but instead select them. " + "To select a number of items, press down the left mouse button and drag it over the items.<p>" + "When you have selected a number of items, you may use cut/copy/paste. These functions are " + "found in the right mouse button menu.</qt>")); + + // Insert buttons. + DoubleClickButton* but; + + but = insert(TEXT, "text", i18n("Text"), + i18n( "<qt>This will insert a text field, where you may write text. The text you write will " + "be matched literally. (i.e. you do not need to escape any characters)</qt>" ) ); + layout->addWidget( but ); + + + but = insert(CHARSET, "characters", i18n("A single character specified in a range"), + i18n("<qt>This will match a single character from a predefined range.<p>" + "When you insert this widget a dialog box will appear, which lets you specify " + "which characters this <i>regexp item</i> will match.</qt>") ); + layout->addWidget( but ); + + + but = insert(DOT, "anychar", i18n("Any character"), + i18n("<qt>This will match any single character</qt>") ); + layout->addWidget( but ); + + + but = insert(REPEAT, "repeat", i18n("Repeated content"), + i18n("<qt>This <i>regexp item</i> will repeat the <i>regexp items</i> it surrounds " + "a specified number of times.<p>" + "The number of times to repeat may be specified using ranges. e.g. You may specify " + "that it should match from 2 to 4 times, that it should match exactly 5 times, or " + "that it should match at least one time.<p>" + "Examples:<br>" + "If you specify that it should match <i>any</i> time, and the content it surrounds " + "is <tt>abc</tt>, then this <i>regexp item</i> will match the empty string, " + "the string <tt>abc</tt>, the string <tt>abcabc</tt>, the string <tt>abcabcabcabc</tt>, " + "etc.</qt>") ); + layout->addWidget( but ); + + + but = insert(ALTN, "altn", i18n("Alternatives"), + i18n("<qt>This <i>regexp item</i> will match any of its alternatives.</p>" + "You specify alternatives by placing <i>regexp items</i> on top of " + "each other inside this widget.</qt>") ); + layout->addWidget( but ); + + + but = insert(COMPOUND, "compound", i18n("Compound regexp"), + i18n("<qt>This <i>regexp item</i> serves two purposes:" + "<ul><li>It makes it possible for you to collapse a huge <i>regexp item</i> into " + "a small box. This makes it easier for you to get an overview of large " + "<i>regexp items</i>. This is especially useful if you load a predefined <i>regexp item</i> " + "you perhaps don't care about the inner workings of.") ); + layout->addWidget( but ); + + + but = insert(BEGLINE, "begline", i18n("Beginning of line"), + i18n("<qt>This will match the beginning of a line.</qt>") ); + layout->addWidget( but ); + + + but = insert(ENDLINE, "endline", i18n("End of line"), + i18n("<qt>This will match the end of a line.</qt>") ); + layout->addWidget( but ); + + + _wordBoundary = insert(WORDBOUNDARY, "wordboundary", i18n("Word boundary"), + i18n("<qt>This asserts a word boundary (This part does not actually match any characters)</qt>") ); + layout->addWidget( _wordBoundary ); + + _nonWordBoundary = insert(NONWORDBOUNDARY, "nonwordboundary", i18n("Non Word boundary"), + i18n("<qt>This asserts a non-word boundary " + "(This part does not actually match any characters)</qt>") ); + layout->addWidget( _nonWordBoundary ); + + _posLookAhead = insert(POSLOOKAHEAD, "poslookahead", i18n("Positive Look Ahead"), + i18n("<qt>This asserts a regular expression (This part does not actually match any characters). " + "You can only use this at the end of a regular expression.</qt>") ); + layout->addWidget( _posLookAhead ); + + _negLookAhead = insert(NEGLOOKAHEAD, "neglookahead", i18n("Negative Look Ahead"), + i18n("<qt>This asserts a regular expression that must not match " + "(This part does not actually match any characters). " + "You can only use this at the end of a regular expression.</qt>") ); + layout->addWidget( _negLookAhead ); +} + +DoubleClickButton* RegExpButtons::insert(RegExpType tp, const char* name, QString tooltip, QString whatsthis) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( QString::fromLatin1( name ) ) ); +#else + QPixmap pix = KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/")+QString::fromLatin1(name) + + QString::fromLatin1(".png") ), KIcon::Toolbar ); +#endif + + DoubleClickButton* but = new DoubleClickButton( pix, this, "RegExpButtons::but"); + + _mapper->setMapping( but, tp ); + + connect( but, SIGNAL( clicked() ), _mapper, SLOT( map() ) ); + connect( but, SIGNAL( clicked() ), this, SLOT( slotSetNonKeepMode() ) ); + connect( but, SIGNAL( doubleClicked() ), this, SLOT( slotSetKeepMode() ) ); + + _grp->insert( but ); + but->setToggleButton( true ); + QToolTip::add( but, tooltip ); + QWhatsThis::add( but, whatsthis ); + + return but; +} + +void RegExpButtons::slotUnSelect() +{ + if ( _grp->selected() ) { + QToolButton *pb = static_cast<QToolButton*>(_grp->selected()); + if (pb) { + pb->setOn( false ); + } + } +} + +void RegExpButtons::slotSetKeepMode( ) +{ + _keepMode = true; +} + +void RegExpButtons::slotSetNonKeepMode( ) +{ + _keepMode = false; +} + +void RegExpButtons::slotSelectNewAction() +{ + if ( ! _keepMode ) { + emit doSelect(); + _grp->setButton(_grp->id(_selectBut)); + } +} + +void RegExpButtons::setFeatures( int features ) +{ + _wordBoundary->setShown( features & RegExpConverter::WordBoundary ); + _nonWordBoundary->setShown( features & RegExpConverter::NonWordBoundary ); + _posLookAhead->setShown( features & RegExpConverter::PosLookAhead ); + _negLookAhead->setShown( features & RegExpConverter::NegLookAhead ); + +} + diff --git a/kregexpeditor/regexpbuttons.h b/kregexpeditor/regexpbuttons.h new file mode 100644 index 0000000..5671810 --- /dev/null +++ b/kregexpeditor/regexpbuttons.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __REGEXPBUTTONS_H +#define __REGEXPBUTTONS_H + +#include <qdockwindow.h> +#include "widgetfactory.h" +class DoubleClickButton; +class QButtonGroup; +class QToolButton; +class QSignalMapper; + + +class RegExpButtons :public QDockWindow +{ + Q_OBJECT + +public: + RegExpButtons( QWidget *parent, const char *name = 0 ); + void setFeatures( int features ); + +protected: + DoubleClickButton* insert(RegExpType tp, const char* file, QString tooltip, QString whatsthis); + +public slots: + void slotSelectNewAction(); + void slotUnSelect(); + +protected slots: + void slotSetKeepMode(); + void slotSetNonKeepMode(); + +signals: + void clicked( int ); + void doSelect(); + +private: + QButtonGroup* _grp; + QToolButton* _selectBut; + QToolButton* _wordBoundary; + QToolButton* _nonWordBoundary; + QToolButton* _posLookAhead; + QToolButton* _negLookAhead; + QSignalMapper* _mapper; // single click Mapper. + + /** + This variable is true if the use wishes to continue editing in the + selected mode after the previous editing is completed (that is, if the + user has double clicked the buttons). + */ + bool _keepMode; +}; + + +#endif // __REGEXPBUTTON_H diff --git a/kregexpeditor/regexpconverter.cpp b/kregexpeditor/regexpconverter.cpp new file mode 100644 index 0000000..2d53e20 --- /dev/null +++ b/kregexpeditor/regexpconverter.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "regexpconverter.h" + +#include "altnregexp.h" +#include "concregexp.h" +#include "lookaheadregexp.h" +#include "textrangeregexp.h" +#include "compoundregexp.h" +#include "dotregexp.h" +#include "positionregexp.h" +#include "repeatregexp.h" +#include "textregexp.h" +#include <qtextedit.h> +#include "regexphighlighter.h" + +RegExpConverter* RegExpConverter::_current = 0; +RegExp* RegExpConverter::parse( const QString&, bool* ok ) +{ + ok = false; + return new DotRegExp( false ); // This method should never be called. +} + +// This function needs to be called toStr rather than toString, as it is not possible to +// over load function across inheritance! +QString RegExpConverter::toStr( RegExp* regexp, bool markSelection ) +{ + switch (regexp->type()) { + case RegExp::CONC: return toString( static_cast<ConcRegExp*>( regexp ), markSelection); + case RegExp::TEXT: return toString( static_cast<TextRegExp*>( regexp ), markSelection ); + case RegExp::DOT: return toString( static_cast<DotRegExp*>( regexp ), markSelection ); + case RegExp::POSITION: return toString( static_cast<PositionRegExp*>( regexp ), markSelection ); + case RegExp::REPEAT: return toString( static_cast<RepeatRegExp*>( regexp ), markSelection ); + case RegExp::ALTN: return toString( static_cast<AltnRegExp*>( regexp ), markSelection ); + case RegExp::COMPOUND: return toString( static_cast<CompoundRegExp*>( regexp ), markSelection ); + case RegExp::LOOKAHEAD: return toString( static_cast<LookAheadRegExp*>( regexp ), markSelection ); + case RegExp::TEXTRANGE: return toString( static_cast<TextRangeRegExp*>( regexp ), markSelection ); + } + qWarning("We shouldn't get here!"); + return QString::fromLatin1( "" ); +} + + +QString RegExpConverter::escape( QString text, QValueList<QChar> chars, QChar escapeChar) const +{ + QString res; + for (unsigned int i=0; i<text.length(); i++) { + for (unsigned int j=0; j<chars.count(); j++) { + if ( text.at(i) == (chars[j]) ) { + res.append( escapeChar ); + break; + } + } + res.append( text.at(i) ); + } + + return res; +} + +/** + Returns a QSyntaxHighlighter to be used in the virifyer widget. +*/ +RegexpHighlighter* RegExpConverter::highlighter( QTextEdit* ) +{ + return 0; +} + +RegExpConverter* RegExpConverter::current() +{ + return _current; +} + +void RegExpConverter::setCurrent( RegExpConverter* converter) +{ + _current = converter; +} + diff --git a/kregexpeditor/regexpconverter.h b/kregexpeditor/regexpconverter.h new file mode 100644 index 0000000..ddb1e54 --- /dev/null +++ b/kregexpeditor/regexpconverter.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef REGEXPCONVERTER_H +#define REGEXPCONVERTER_H + +#include <qstring.h> +#include <qvaluelist.h> + +class QTextEdit; +class AltnRegExp; +class ConcRegExp; +class LookAheadRegExp; +class TextRangeRegExp; +class CompoundRegExp; +class DotRegExp; +class PositionRegExp; +class RepeatRegExp; +class TextRegExp; +class RegexpHighlighter; +class RegExp; + +class RegExpConverter +{ +public: + enum Features { + WordBoundary = 0x01, + NonWordBoundary = 0x02, + WordStart = 0x04, + WordEnd = 0x08, + PosLookAhead = 0x10, + NegLookAhead = 0x20, + CharacterRangeNonItems = 0x40, + ExtRange = 0x80 + }; + + virtual bool canParse() = 0; + virtual QString name() = 0; + virtual int features() = 0; + virtual RegExp* parse( const QString&, bool* ok ); + QString toStr( RegExp*, bool markSelection ); + virtual RegexpHighlighter* highlighter( QTextEdit* ); + + static void setCurrent( RegExpConverter* ); + static RegExpConverter* current(); + +protected: + virtual QString toString( AltnRegExp*, bool markSelection ) = 0; + virtual QString toString( ConcRegExp*, bool markSelection ) = 0; + virtual QString toString( LookAheadRegExp*, bool markSelection ) = 0; + virtual QString toString( TextRangeRegExp*, bool markSelection ) = 0; + virtual QString toString( CompoundRegExp*, bool markSelection ) = 0; + virtual QString toString( DotRegExp*, bool markSelection ) = 0; + virtual QString toString( PositionRegExp*, bool markSelection ) = 0; + virtual QString toString( RepeatRegExp*, bool markSelection ) = 0; + virtual QString toString( TextRegExp*, bool markSelection ) = 0; + QString escape( QString text, QValueList<QChar> chars, QChar escapeChar) const; + +private: + static RegExpConverter* _current; +}; + +#endif /* REGEXPCONVERTER_H */ + diff --git a/kregexpeditor/regexphighlighter.cpp b/kregexpeditor/regexphighlighter.cpp new file mode 100644 index 0000000..3034ee1 --- /dev/null +++ b/kregexpeditor/regexphighlighter.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "regexphighlighter.h" + +RegexpHighlighter::RegexpHighlighter( QTextEdit* edit ) + :QSyntaxHighlighter( edit ), _caseSensitive( false ), _minimal( false ) +{ +} + +void RegexpHighlighter::setRegExp( const QString& regexp ) +{ + _regexp = regexp; +} + +void RegexpHighlighter::setCaseSensitive( bool b ) +{ + _caseSensitive = b; +} + +void RegexpHighlighter::setMinimal( bool b ) +{ + _minimal = b; +} + + + + + diff --git a/kregexpeditor/regexphighlighter.h b/kregexpeditor/regexphighlighter.h new file mode 100644 index 0000000..92219b1 --- /dev/null +++ b/kregexpeditor/regexphighlighter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef REGEXPHIGHLIGHTER_H +#define REGEXPHIGHLIGHTER_H +#include <qsyntaxhighlighter.h> + +class RegexpHighlighter :public QSyntaxHighlighter +{ +public: + RegexpHighlighter( QTextEdit* edit ); + void setRegExp( const QString& regexp ); + void setCaseSensitive( bool ); + void setMinimal( bool ); + +protected: + QString _regexp; + bool _caseSensitive, _minimal; + +}; + +#endif /* REGEXPHIGHLIGHTER_H */ + diff --git a/kregexpeditor/regexpwidget.cpp b/kregexpeditor/regexpwidget.cpp new file mode 100644 index 0000000..2ee2aa7 --- /dev/null +++ b/kregexpeditor/regexpwidget.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include "regexpwidget.moc" +#endif + +#include "regexpwidget.h" +#include <iostream> +#include <qpainter.h> +#include <qcursor.h> +#include "concwidget.h" +#include "dragaccepter.h" + +const int RegExpWidget::pw = 1; +const int RegExpWidget::bdSize = 5; +const int RegExpWidget::space = 5; + +RegExpWidget::RegExpWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : QWidget(parent, name ? name : "RegExpWidget", WNoMousePropagation ), + _editorWindow( editorWindow ), _isSelected( false ), _isToplevel( false ) +{ +} + + +void RegExpWidget::addNewChild(DragAccepter *, RegExpWidget *) +{ + qFatal("This widget should not expect any children"); +} + +void RegExpWidget::addNewConcChild(DragAccepter *, ConcWidget *) +{ + qFatal("This widget should not expect any children"); +} + +void RegExpWidget::setConcChild(ConcWidget *) +{ + qFatal("This widget should not expect any children"); +} + +bool RegExpWidget::updateSelection(bool parentSelected) +{ + bool selected = ( parentSelected || + _editorWindow->selectionOverlap( mapToGlobal( QPoint(0,0) ), size() ) ) + && !_isToplevel; + + if ( _isSelected != selected ) { + // Selection state changed + _isSelected = selected; + repaint(); + return true; + } + return false; +} + +void RegExpWidget::drawPossibleSelection( QPainter& painter, QSize mySize ) +{ + if ( _isSelected ) { + painter.fillRect( 0, 0, mySize.width(), mySize.height(), QBrush( gray ) ); + } +} + +bool RegExpWidget::isSelected() const +{ + return _isSelected; +} + +bool RegExpWidget::hasSelection() const +{ + return _isSelected; +} + +void RegExpWidget::clearSelection() +{ + _isSelected = false; +} + +void RegExpWidget::applyRegExpToSelection( RegExpType ) +{ + qFatal("This method should not be called for this widget"); +} + +void RegExpWidget::deleteSelection() +{ + qFatal("This method should be overridden if needed!"); +} + +RegExp* RegExpWidget::selection() const +{ + return regExp(); +} + +int RegExpWidget::edit() +{ + qFatal("This method should be overridden if needed!"); + return 0; // Compiler shut up +} + +void RegExpWidget::mousePressEvent ( QMouseEvent* event ) +{ + if ( _editorWindow->isPasteing() || _editorWindow->isInserting() ) + return; + + if ( event->button() == LeftButton ) { + if ( ! _editorWindow->pointSelected( QCursor::pos() ) ) { + _editorWindow->clearSelection( true ); + if ( dynamic_cast<DragAccepter*>(this) == 0 && dynamic_cast<ConcWidget*>(this) == 0 ) { + selectWidget( true ); + } + } + + QMouseEvent ev( event->type(), mapTo(_editorWindow, event->pos()), + event->button(), event->state()); + QApplication::sendEvent( _editorWindow, &ev ); + } + else if ( event->button() == RightButton ) { + _editorWindow->showRMBMenu( true ); + } + + // currently (Qt3.0) it seems like qt do not accept that the accept flag is set, + // and thus sends the event to the parent - given that the following line is in. + // It doesn't make any change to leave it out. + // 25 Oct. 2001 19:03 -- Jesper K. Pedersen + // QWidget::mousePressEvent( event ); +} + +void RegExpWidget::mouseReleaseEvent( QMouseEvent* ) +{ + if ( _editorWindow->isInserting() && acceptWidgetInsert( _editorWindow->insertType() ) ) { + if ( !_editorWindow->hasSelection() ) + _isSelected = true; + + _editorWindow->applyRegExpToSelection( _editorWindow->insertType() ); + _editorWindow->clearSelection( true ); + _editorWindow->updateContent( this ); + _editorWindow->slotEndActions(); + _editorWindow->updateCursorUnderPoint(); + } +} + +QRect RegExpWidget::selectionRect() const +{ + return QRect( mapToGlobal( QPoint(0,0) ), size() ); +} + + +void RegExpWidget::enterEvent( QEvent * ) +{ + updateCursorShape(); +} + +void RegExpWidget::updateCursorShape() +{ + QCursor cursor; + + if ( _editorWindow->isPasteing() ) { + if ( acceptWidgetPaste() ) + cursor = CrossCursor; + else + cursor = ForbiddenCursor; + } + else if ( _editorWindow->isInserting() ) { + if ( acceptWidgetInsert( _editorWindow->insertType() ) ) + cursor = CrossCursor; + else + cursor = ForbiddenCursor; + } + else + cursor = arrowCursor; + + setCursor( cursor ); +} + +void RegExpWidget::updateCursorRecursively() +{ + updateCursorShape(); +} + + +bool RegExpWidget::acceptWidgetPaste() const +{ + return false; +} + +bool RegExpWidget::acceptWidgetInsert( RegExpType tp ) const +{ + return WidgetFactory::isContainer( tp ); +} + +RegExpWidget* RegExpWidget::widgetUnderPoint( QPoint globalPos, bool ) +{ + if ( QRect(mapToGlobal( QPoint(0,0) ), size() ).contains( globalPos ) ) + return this; + else + return 0; +} + +void RegExpWidget::selectWidget( bool sel) +{ + _isSelected = sel; + update(); +} + +void RegExpWidget::updateAll() +{ + update(); +} + + diff --git a/kregexpeditor/regexpwidget.h b/kregexpeditor/regexpwidget.h new file mode 100644 index 0000000..e0c038d --- /dev/null +++ b/kregexpeditor/regexpwidget.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __regexpwidget +#define __regexpwidget + +#include "editorwindow.h" + +class DragAccepter; +class RegExp; +class ConcWidget; +class RegExpEditorWindow; + +/** + Base class for all regular expression widgets. + @internal +*/ +class RegExpWidget :public QWidget +{ +Q_OBJECT + +public: + RegExpWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + + /*====================================================================== + Construction, child management + ======================================================================*/ + /** + Add `child' to the parent of this widget in place of `accepter' + This method only applies to container widgets (see @ref + SingleContainerWidget, and @ref MultiContainerWidget). + */ + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + + /** + Inserts all the children of `child' into this widget in place of + `accepter'. + This method only applies to container widgets (see @ref + SingleContainerWidget, and @ref MultiContainerWidget). + */ + virtual void addNewConcChild(DragAccepter *accepter, ConcWidget *child); + + /** + Set `child' as the ConcWidget. This method should only be invoked when + the widget has just been constructed. + This method only applies to container widgets (see @ref + SingleContainerWidget, and @ref MultiContainerWidget). + */ + virtual void setConcChild(ConcWidget *child); + + /* ====================================================================== + Selection + ======================================================================*/ + + /** + Marks this widget as being the immediate child of the editor + window. That is the topmost regular expression widget. + + This information is necessary when drawing the widget, and when + drawing the selection. + */ + void setToplevel() { _isToplevel = true; } + + /** + Returns true if this widget is selected. + */ + virtual bool isSelected() const; + + /** + Returns true if this widget or one of its children is selected. + */ + virtual bool hasSelection() const; + + virtual void updateAll(); + + /** + Update selection information for this widget. + @param parentSelected indicates whether the parent is selected. + @return true if the selection state has changed for the widget since + the last time the widget was painted. `repaint' is invoked on the widget if + selection state is changed, to ensure that selection is visible. + */ + virtual bool updateSelection(bool parentSelected); + + /** + Clears the selection and repaints the widget if `update' is true. + */ + virtual void clearSelection(); + + /** + Deletes the regexp widgets containing selection. + */ + virtual void deleteSelection(); + + /** + See @ref RegExpEditorWindow::applyRegExpToSelection + */ + virtual void applyRegExpToSelection( RegExpType type ); + + /** + Validate that selection is OK. Returns false if not. + + Only one alternative may be selected in @ref AltnWidget. This + limitation is to make implementation of a number of functions simpler. + */ + virtual bool validateSelection() const { return true; } + + /** + Returns the rectangle which makes up the selection. + */ + virtual QRect selectionRect() const; + + /** Selects the RegExp widget and all its chidlren*/ + virtual void selectWidget( bool sel ); + + /*====================================================================== + Misc + ======================================================================*/ + + /** Returns the RegExp widget, which is rooted in this regexp widget. */ + virtual RegExp* regExp() const = 0; + + /** returns the current selection */ + virtual RegExp* selection() const; + + /** returns the type of this regular expression widget. */ + virtual RegExpType type() const = 0; + + /** + updates the cursor to be one of + @li normal selection cursor + @li accept cursor for insert/paste + @li reject cursor for insert/paste + */ + void updateCursorShape(); + + virtual void updateCursorRecursively(); + + /** + Returns the regexp widget under point. If `justVisibleWidgets' is + true, @ref ConcWidget is ignored. That is, a ConcWidget will not be returned. + */ + virtual RegExpWidget* widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ); + + /** + Returns the widget under point which can be edited. That is the + "innermost" widget editable. + */ + virtual RegExpWidget* findWidgetToEdit( QPoint /* globalPos */) { return 0; } + + /** + Edits the current widget. That is, bring up the dialog, which is + available for @ref ConcWidget, @ref CompoundWidget, and @ref + CharactersWidget. + */ + virtual int edit(); + +protected: + /** Draws a selection rectangle for the current widget. */ + virtual void drawPossibleSelection( QPainter& painter, QSize mySize); + + /** Returns true if the widget accepts paste actions. */ + virtual bool acceptWidgetPaste() const; + + /** + Returns true if the widget accept the given RegExpType to be inserted + */ + virtual bool acceptWidgetInsert( RegExpType ) const; + + virtual void mousePressEvent ( QMouseEvent* event ); + + virtual void mouseReleaseEvent( QMouseEvent* ); + virtual void enterEvent( QEvent * ); + + RegExpEditorWindow* _editorWindow; + + /** True if the widget is selected. */ + bool _isSelected; + + /** See @ref setToplevel */ + bool _isToplevel; + + static const int pw; // width of pen + static const int bdSize; // width between borders and text etc. + static const int space; // TODO. +}; + +#endif // __regexpwidget diff --git a/kregexpeditor/repeatregexp.cpp b/kregexpeditor/repeatregexp.cpp new file mode 100644 index 0000000..d58736c --- /dev/null +++ b/kregexpeditor/repeatregexp.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include "kmessagebox.h" + #include <klocale.h> +#endif + +#include "repeatregexp.h" + +RepeatRegExp::RepeatRegExp( bool selected, int lower, int upper, RegExp* child) : RegExp( selected ) +{ + _lower = lower; + _upper = upper; + _child = child; + if (child) + addChild( child ); +} + +bool RepeatRegExp::check( ErrorMap& map, bool first, bool last ) +{ + _child->check( map, first, last ); + return ( _lower == 0 ); +} + +QDomNode RepeatRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit("Repeat") ); + top.setAttribute( QString::fromLocal8Bit("lower"), _lower ); + top.setAttribute( QString::fromLocal8Bit("upper"), _upper ); + top.appendChild( _child->toXml( doc ) ); + return top; +} + +bool RepeatRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Repeat" ) ); + QString lower = top.attribute( QString::fromLocal8Bit("lower"), QString::fromLocal8Bit("0") ); + QString upper = top.attribute( QString::fromLocal8Bit("upper"), QString::fromLocal8Bit("0") ); + bool ok; + _lower = lower.toInt( &ok ); + if ( !ok ) { + KMessageBox::sorry( 0, i18n("<p>Value for attribute <b>%1</b> was not an integer for element " + "<b>%2</b></p><p>It contained the value <b>%3</b></p>") + .arg(QString::fromLatin1("lower")).arg(QString::fromLatin1("Repeat")).arg(lower), + i18n("Error While Loading From XML File") ) ; + _lower = 0; + } + _upper = upper.toInt( &ok ); + if ( !ok ) { + KMessageBox::sorry( 0, i18n("<p>Value for attribute <b>%1</b> was not an integer for element " + "<b>%2</b></p><p>It contained the value <b>%3</b></p>") + .arg(QString::fromLatin1("upper")).arg(QString::fromLatin1("Repeat")).arg(upper), + i18n("Error While Loading From XML File") ) ; + _upper = -1; + } + + _child = readRegExp( top, version ); + if ( _child ) { + addChild( _child ); + return true; + } + else + return false; +} + +bool RepeatRegExp::operator==( const RegExp& other ) const +{ + if ( type() != other.type() ) + return false; + + const RepeatRegExp& theOther = dynamic_cast<const RepeatRegExp&>( other ); + if ( _lower != theOther._lower || _upper != theOther._upper ) + return false; + + return (*_child == *(theOther._child) ); +} + diff --git a/kregexpeditor/repeatregexp.h b/kregexpeditor/repeatregexp.h new file mode 100644 index 0000000..21e32cd --- /dev/null +++ b/kregexpeditor/repeatregexp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __REPEATREGEXP_H +#define __REPEATREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `repeated content' regular expression + @internal +*/ +class RepeatRegExp :public RegExp +{ +public: + RepeatRegExp( bool selected, int lower = 0, int upper = 0, RegExp* child = 0); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 3;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + int min() const { return _lower; } + int max() const { return _upper; } + RegExp* child() const { return _child; } + virtual RegExpType type() const { return REPEAT;} + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ) { _child->replacePart( replacement ); } + +private: + int _lower; + int _upper; + RegExp* _child; +}; + +#endif // __REPEATREGEXP_H diff --git a/kregexpeditor/repeatwidget.cpp b/kregexpeditor/repeatwidget.cpp new file mode 100644 index 0000000..27215e4 --- /dev/null +++ b/kregexpeditor/repeatwidget.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kdialogbase.h> + #include "repeatwidget.moc" +#endif + +#include "repeatwidget.h" +#include "concwidget.h" +#include "repeatregexp.h" +#include <qpainter.h> +#include <qcursor.h> +#include <qspinbox.h> +#include <qradiobutton.h> +#include <qlayout.h> +#include <qgrid.h> +#include <qvbuttongroup.h> +#include "kwidgetstreamer.h" + +RepeatWidget::RepeatWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : SingleContainerWidget(editorWindow, parent, name ? name : "RepeatWidget") +{ + _child = new ConcWidget(editorWindow, this); + init(); +} + +RepeatWidget::RepeatWidget( RepeatRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + :SingleContainerWidget( editorWindow, parent, name ) +{ + init(); + RegExpWidget* child = WidgetFactory::createWidget( regexp->child(), editorWindow, this ); + if ( ! (_child = dynamic_cast<ConcWidget*>( child ) ) ) + _child = new ConcWidget( editorWindow, child, this ); + + if ( regexp->max() == -1 ) { + if ( regexp->min() == 0 ) { + _content->set( RepeatRangeWindow::ANY, regexp->min(), regexp->max() ); + } + else { + _content->set( RepeatRangeWindow::ATLEAST, regexp->min(), regexp->max() ); + } + } + else { + if ( regexp->min() == 0 ) { + _content->set( RepeatRangeWindow::ATMOST, regexp->min(), regexp->max() ); + } + else if ( regexp->min() == regexp->max() ) { + _content->set( RepeatRangeWindow::EXACTLY, regexp->min(), regexp->max() ); + } + else { + _content->set( RepeatRangeWindow::MINMAX, regexp->min(), regexp->max() ); + } + } +} + +void RepeatWidget::init() +{ + _configWindow = new KDialogBase( this, "_configWindow", true, + i18n("Number of Times to Repeat Content"), + KDialogBase::Ok | KDialogBase::Cancel); + _content = new RepeatRangeWindow( _configWindow ); + _configWindow->setMainWidget( _content ); + connect( _configWindow, SIGNAL( cancelClicked() ), this, SLOT( slotConfigCanceled() ) ); + connect(_configWindow, SIGNAL(finished()), this, SLOT(slotConfigWindowClosed())); +} + + +QSize RepeatWidget::sizeHint() const +{ + // TODO: Merge with LookAheadWidget::sizeHint + QFontMetrics metrics = fontMetrics(); + _textSize = metrics.size( 0, _content->text() ); + + _childSize = _child->sizeHint(); + + int height = _textSize.height() + bdSize + _childSize.height() + bdSize + 2*pw; + int width = 2 * pw + QMAX(_childSize.width(), 4*bdSize + _textSize.width()); + return QSize(width,height); +} + +void RepeatWidget::paintEvent( QPaintEvent *e ) +{ + // TODO: Merge with LookAheadWidget::paintEvent + QSize mySize = sizeHint(); + QPainter painter(this); + + drawPossibleSelection( painter, mySize ); + + // move the child to its position and resize it. + _child->move(pw,_textSize.height()+bdSize); + QSize curChildSize = _child->size(); + QSize newChildSize = QSize(mySize.width() - 2*pw, _childSize.height()); + if ( curChildSize != newChildSize ) { + _child->resize(newChildSize); + // I resized the child, so give it a chance to relect thus. + _child->update(); + } + + // Draw the border and the text. + int startY = _textSize.height()/2; + + // Top lines and text + painter.drawLine(pw,startY,bdSize,startY); + painter.drawText(pw+2*bdSize,0,_textSize.width(), _textSize.height(),0, + _content->text()); + int offset = pw + 3*bdSize + _textSize.width(); + painter.drawLine(offset,startY,mySize.width()-pw,startY); + + // horizontal lines + painter.drawLine(0,startY,0,mySize.height()-pw); + painter.drawLine(mySize.width()-pw,startY,mySize.width()-pw, mySize.height()-pw); + + // buttom line + painter.drawLine(0, mySize.height()-pw, mySize.width()-pw, mySize.height()-pw); + + SingleContainerWidget::paintEvent(e); +} + +RegExp* RepeatWidget::regExp() const +{ + return new RepeatRegExp( isSelected(), _content->min(), _content->max(), _child->regExp() ); +} + +void RepeatWidget::slotConfigWindowClosed() +{ + _editorWindow->updateContent( 0 ); + update(); +} + +void RepeatWidget::slotConfigCanceled() +{ + QDataStream stream( _backup, IO_ReadOnly ); + KWidgetStreamer streamer; + streamer.fromStream( stream, _content ); + repaint(); +} + +int RepeatWidget::edit() +{ + _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width()/2, + _configWindow->sizeHint().height()/2) ); + QDataStream stream( _backup, IO_WriteOnly ); + KWidgetStreamer streamer; + streamer.toStream( _content, stream ); + + return _configWindow->exec(); +} + +//-------------------------------------------------------------------------------- +RepeatRangeWindow::RepeatRangeWindow( QWidget* parent, const char* name ) + : QVBox( parent, name ? name : "RepeatRangeWindow" ) +{ + setSpacing( 6 ); + + _group = new QVButtonGroup( i18n("Times to Match"), this, "groupbox" ); + + // Any number of times + QRadioButton* radioBut = new QRadioButton(i18n("Any number of times (including zero times)"), + _group, + "RepeatRangeWindow::choice any times"); + + _group->insert(radioBut, ANY); + + QWidget* container = new QWidget( _group ); + QHBoxLayout* lay = new QHBoxLayout( container ); + QGrid* grid = new QGrid( 3, container ); + grid->setSpacing( 5 ); + + lay->addWidget( grid ); + lay->addStretch( 1 ); + + createLine( grid, i18n( "At least" ), &_leastTimes, ATLEAST ); + createLine( grid, i18n( "At most" ), &_mostTimes, ATMOST ); + createLine( grid, i18n( "Exactly" ), &_exactlyTimes, EXACTLY ); + + // from ___ to ___ times + radioBut = new QRadioButton(i18n( "From" ), grid, "RepeatRangeWindow::from"); + _group->insert( radioBut, MINMAX ); + + _rangeFrom = new QSpinBox( 1, 999, 1, grid); + + QHBox* box = new QHBox( grid ); + box->setSpacing( 5 ); + + (void) new QLabel(i18n( "to" ), box); + _rangeTo = new QSpinBox( 1, 999, 1, box ); + (void) new QLabel( i18n( "time(s)" ), box ); + + connect( _rangeFrom, SIGNAL( valueChanged( int ) ), this, SLOT( slotUpdateMaxVal( int ) ) ); + connect( _rangeTo, SIGNAL( valueChanged( int ) ), this, SLOT( slotUpdateMinVal( int ) ) ); + + // set a default button. + _group->setButton(ANY); + slotItemChange( ANY ); + + + connect( _group, SIGNAL( clicked( int ) ), this, SLOT( slotItemChange( int ) ) ); +} + + +void RepeatRangeWindow::createLine( QWidget* parent, QString text, QSpinBox** spin, REPEATTYPE tp ) +{ + + QRadioButton* radioBut = new QRadioButton(text, parent); + *spin = new QSpinBox( 1, 999, 1, parent); + (*spin)->setValue(1); + + (void) new QLabel(i18n("time(s)"), parent); + _group->insert(radioBut, tp); +} + +void RepeatRangeWindow::slotItemChange( int which ) +{ + _leastTimes->setEnabled( false ); + _mostTimes->setEnabled( false ); + _exactlyTimes->setEnabled( false ); + _rangeFrom->setEnabled( false ); + _rangeTo->setEnabled( false ); + + switch ( which ) { + case ANY: break; + case ATLEAST: _leastTimes->setEnabled( true ); break; + case ATMOST: _mostTimes->setEnabled( true ); break; + case EXACTLY: _exactlyTimes->setEnabled( true ); break; + case MINMAX: + _rangeFrom->setEnabled( true ); + _rangeTo->setEnabled( true ); + break; + } +} + +void RepeatRangeWindow::slotUpdateMinVal( int maxVal ) +{ + if ( _rangeFrom->value() > maxVal ) { + _rangeFrom->setValue( maxVal ); + } +} + +void RepeatRangeWindow::slotUpdateMaxVal( int minVal ) +{ + if ( _rangeTo->value() < minVal ) { + _rangeTo->setValue( minVal ); + } +} + +QString RepeatRangeWindow::text() +{ + switch ( _group->id(_group->selected()) ) { + case ANY: return i18n("Repeated Any Number of Times"); + case ATLEAST: return i18n("Repeated at Least 1 Time", "Repeated at Least %n Times", _leastTimes->value() ); + case ATMOST: return i18n("Repeated at Most 1 Time", "Repeated at Most %n Times", _mostTimes->value() ); + case EXACTLY: return i18n("Repeated Exactly 1 Time", "Repeated Exactly %n Times", _exactlyTimes->value() ); + case MINMAX: return i18n("Repeated From %1 to %2 Times") + .arg( _rangeFrom->value() ).arg( _rangeTo->value() ); + } + qFatal("Fall through!"); + return QString::fromLocal8Bit(""); +} + +int RepeatRangeWindow::min() +{ + switch ( _group->id(_group->selected()) ) { + case ANY: return 0; + case ATLEAST: return _leastTimes->value(); + case ATMOST: return 0; + case EXACTLY: return _exactlyTimes->value(); + case MINMAX: return _rangeFrom->value(); + } + qFatal("Fall through!"); + return -1; +} + +int RepeatRangeWindow::max() +{ + switch ( _group->id(_group->selected()) ) { + case ANY: return -1; + case ATLEAST: return -1; + case ATMOST: return _mostTimes->value(); + case EXACTLY: return _exactlyTimes->value(); + case MINMAX: return _rangeTo->value(); + } + qFatal("Fall through!"); + return -1; +} + +void RepeatRangeWindow::set( REPEATTYPE tp, int min, int max ) +{ + _group->setButton( tp ); + switch ( tp ) { + case ANY: + break; + case ATLEAST: + _leastTimes->setValue( min ); + break; + case ATMOST: + _mostTimes->setValue( max ); + break; + case EXACTLY: + _exactlyTimes->setValue( min ); + break; + case MINMAX: + _rangeFrom->setValue( min ); + _rangeTo->setValue( max ); + break; + } +} diff --git a/kregexpeditor/repeatwidget.h b/kregexpeditor/repeatwidget.h new file mode 100644 index 0000000..434b4cb --- /dev/null +++ b/kregexpeditor/repeatwidget.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __repeatwidget +#define __repeatwidget + +#include "singlecontainerwidget.h" +#include <qvbox.h> +class QButtonGroup; +class KDialogBase; +class QCheckBox; +class QSpinBox; +class RepeatRegExp; + +/** + Widget containging the configuration for a @ref RepeatWidget + @internal +*/ +class RepeatRangeWindow :public QVBox +{ +Q_OBJECT + +public: + enum REPEATTYPE {ANY, ATLEAST, ATMOST, EXACTLY, MINMAX}; + + RepeatRangeWindow( QWidget* parent, const char* name = 0 ); + QString text(); + int min(); + int max(); + void set( REPEATTYPE tp, int min, int max ); + +protected slots: + void slotItemChange( int which ); + void slotUpdateMinVal( int minVal ); + void slotUpdateMaxVal( int minVal ); + + +private: + void createLine( QWidget* parent, QString text, QSpinBox** spin, REPEATTYPE tp ); + + QSpinBox* _leastTimes; + QSpinBox* _mostTimes; + QSpinBox* _exactlyTimes; + QSpinBox* _rangeFrom; + QSpinBox* _rangeTo; + QButtonGroup* _group; +}; + + + + + +/** + RegExp widget for `repeated content' + @internal +*/ +class RepeatWidget :public SingleContainerWidget +{ +Q_OBJECT + +public: + RepeatWidget( RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + RepeatWidget( RepeatRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + void init(); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return REPEAT; } + virtual int edit(); + +protected: + virtual void paintEvent( QPaintEvent *e ); + +protected slots: + void slotConfigCanceled(); + void slotConfigWindowClosed(); + +private: + KDialogBase* _configWindow; + RepeatRangeWindow* _content; + + mutable QSize _textSize; + mutable QSize _childSize; + QByteArray _backup; +}; + + +#endif // __repeatwidget diff --git a/kregexpeditor/scrollededitorwindow.cpp b/kregexpeditor/scrollededitorwindow.cpp new file mode 100644 index 0000000..8518db9 --- /dev/null +++ b/kregexpeditor/scrollededitorwindow.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "scrollededitorwindow.moc" +#endif + +#include "scrollededitorwindow.h" +#include "editorwindow.h" + +RegExpScrolledEditorWindow::RegExpScrolledEditorWindow( QWidget* parent, const char* name) + : QWidget(parent, name) +{ + _scrollView = new QScrollView( this ); + _editorWindow = new RegExpEditorWindow( _scrollView->viewport()); + _scrollView->addChild( _editorWindow ); + _scrollView->setResizePolicy( QScrollView::Manual ); + + connect( _editorWindow, SIGNAL( contentChanged( QPoint ) ), + this, SLOT( slotUpdateContentSize( QPoint ) ) ); + + connect( _editorWindow, SIGNAL( scrolling( QPoint ) ), + this, SLOT( slotScroll( QPoint ) ) ); + + connect( _editorWindow, SIGNAL( doneEditing() ), this, SIGNAL( doneEditing() ) ); + + connect( _editorWindow, SIGNAL( change() ), this, SIGNAL( change() ) ); + connect( _editorWindow, SIGNAL( savedRegexp() ), this, SIGNAL( savedRegexp() ) ); + + connect( _editorWindow, SIGNAL( anythingSelected(bool) ), this, SIGNAL( anythingSelected(bool) ) ); + connect( _editorWindow, SIGNAL( anythingOnClipboard(bool) ), this, SIGNAL( anythingOnClipboard(bool) ) ); + connect( _editorWindow, SIGNAL( canSave(bool) ), this, SIGNAL( canSave(bool) ) ); + connect( _editorWindow, SIGNAL( verifyRegExp() ), this, SIGNAL( verifyRegExp() ) ); +} + +void RegExpScrolledEditorWindow::slotSetRegExp( RegExp* regexp ) +{ + _editorWindow->slotSetRegExp( regexp ); + slotUpdateContentSize(QPoint()); +} + +void RegExpScrolledEditorWindow::slotInsertRegExp( int tp) +{ + _editorWindow->slotInsertRegExp( (RegExpType) tp ); +} + +void RegExpScrolledEditorWindow::slotInsertRegExp( RegExp* regexp) +{ + _editorWindow->slotInsertRegExp( regexp ); +} + +void RegExpScrolledEditorWindow::slotDeleteSelection() +{ + _editorWindow->slotDeleteSelection(); +} + +void RegExpScrolledEditorWindow::slotDoSelect() +{ + _editorWindow->slotDoSelect(); +} + +void RegExpScrolledEditorWindow::slotCut() +{ + _editorWindow->slotCut(); +} + +void RegExpScrolledEditorWindow::slotCopy() +{ + _editorWindow->slotCopy(); +} + +void RegExpScrolledEditorWindow::slotPaste() +{ + _editorWindow->slotStartPasteAction(); +} + +void RegExpScrolledEditorWindow::slotSave() +{ + _editorWindow->slotSave(); +} + +RegExp* RegExpScrolledEditorWindow::regExp() +{ + return _editorWindow->regExp(); +} + +void RegExpScrolledEditorWindow::resizeEvent( QResizeEvent *event ) +{ + _scrollView->resize( event->size() ); + slotUpdateContentSize(QPoint()); +} + +void RegExpScrolledEditorWindow::slotUpdateContentSize( QPoint focusPoint ) +{ + QSize childSize = _editorWindow->sizeHint(); + QSize vpSize = _scrollView->viewportSize(10,10); + + bool change = false; + + if ( childSize.width() < vpSize.width() ) { + childSize.setWidth( vpSize.width() ); + change = true; + } + + if ( childSize.height() < vpSize.height() ) { + childSize.setHeight( vpSize.height() ); + change = true; + } + + if ( change || + _scrollView->contentsWidth() != childSize.width() || + _scrollView->contentsHeight() != childSize.height() ) { + _editorWindow->resize( childSize ); + _scrollView->resizeContents( childSize.width(), childSize.height() ); + } + + if ( !focusPoint.isNull() ) { + _scrollView->ensureVisible ( focusPoint.x(), focusPoint.y(), 250,250 ); + } + +} + + +// TODO: add timers, which will make the widget scroll when mouse is located +// outside the QScrollView. +void RegExpScrolledEditorWindow::slotScroll( QPoint focusPoint ) +{ + _scrollView->ensureVisible( focusPoint.x(), focusPoint.y() ); +} + diff --git a/kregexpeditor/scrollededitorwindow.h b/kregexpeditor/scrollededitorwindow.h new file mode 100644 index 0000000..725b224 --- /dev/null +++ b/kregexpeditor/scrollededitorwindow.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __scrolledEditorWindow +#define __scrolledEditorWindow + +#include <qhbox.h> +class QScrollView; +class RegExpEditorWindow; +class RegExp; + + +/** + Regular Expression editor window. +*/ +class RegExpScrolledEditorWindow :public QWidget +{ + Q_OBJECT +public: + RegExpScrolledEditorWindow( QWidget *parent = 0, const char* name = 0); + RegExp* regExp(); + +private: + RegExpScrolledEditorWindow() {}; // Dont use! + + +protected: + virtual void resizeEvent( QResizeEvent* ); + +public slots: + void slotSetRegExp( RegExp* ); + void slotInsertRegExp( int ); + void slotInsertRegExp( RegExp* ); + void slotDeleteSelection(); + void slotDoSelect(); + void slotCut(); + void slotCopy(); + void slotSave(); + void slotPaste(); + +protected slots: + void slotUpdateContentSize( QPoint focusPoint ); + void slotScroll( QPoint focusPoint ); + + signals: + /** + This signal is emited when the user has completed an editing + action. The application may chose to call @ref slotDoSelect as a + consequence to reset to selection mode. + */ + void doneEditing(); + + /** + This signal is emited whenever a change has taked place in the editor widget + */ + void change(); + + /** + This signal is emitted when the user saves a regular expression. + */ + void savedRegexp(); + + void anythingSelected( bool ); + void anythingOnClipboard( bool ); + void canSave( bool ); + + /** + This signal is emitted when the regular expression has changed, or + when the selection has changed. + */ + void verifyRegExp(); + +private: + RegExpEditorWindow* _editorWindow; + QScrollView* _scrollView; +}; + +#endif // __scrolledEditorWindow diff --git a/kregexpeditor/selectablelineedit.cpp b/kregexpeditor/selectablelineedit.cpp new file mode 100644 index 0000000..98aff72 --- /dev/null +++ b/kregexpeditor/selectablelineedit.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QT_ONLY + #include "selectablelineedit.moc" +#endif + +#include "selectablelineedit.h" + +SelectableLineEdit::SelectableLineEdit( RegExpWidget* owner, QWidget* parent, const char* name) + : QLineEdit( parent, name ), _owner(owner) +{ + connect( this, SIGNAL( textChanged( const QString & ) ), this, + SLOT( slotKeyPressed() ) ); + setAcceptDrops( false ); +} + +void SelectableLineEdit::setSelected( bool selected ) +{ + if ( selected ) { + QPalette pal = palette().copy(); + pal.setBrush( QColorGroup::Base, gray ); + setPalette( pal ); + } + else { + unsetPalette(); + } + repaint(); +} + +QSize SelectableLineEdit::sizeHint() const +{ + int frameWidth = frame() ? 8 : 4; // from QLineEdit source + QFontMetrics metrics = fontMetrics(); + int actualSize = metrics.width( text() ); + int charWidth = metrics.maxWidth(); + int height = QLineEdit::sizeHint().height(); + + int width; + if ( hasFocus() ) + width = actualSize+6*charWidth + frameWidth; + else + width = QMAX(actualSize, charWidth) + frameWidth; + return QSize( width , height ); +} + +void SelectableLineEdit::slotKeyPressed() +{ + int frameWidth = frame() ? 8 : 4; // from QLineEdit source + + QFontMetrics metrics = fontMetrics(); + int actualSize = metrics.width( text() ); + + if ( actualSize > size().width()-frameWidth ) { + repaint(); + emit parentPleaseUpdate(); + } +} diff --git a/kregexpeditor/selectablelineedit.h b/kregexpeditor/selectablelineedit.h new file mode 100644 index 0000000..653d85c --- /dev/null +++ b/kregexpeditor/selectablelineedit.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __selectablelineedit +#define __selectablelineedit +#include <qlineedit.h> +class RegExpWidget; + +/** + A specialized QLineEdit for use in @ref TextWidget. + + This widget has two main features: + @li when the @ref TextWidget which contains it is selected, then the + line edit is grayed like the rest of the widgets. + @li When the widget does not have the focus, it is resized to only be + large enough to contain the text written in it. + + @internal +*/ +class SelectableLineEdit :public QLineEdit +{ +Q_OBJECT + +public: + SelectableLineEdit( RegExpWidget* owner, QWidget* parent = 0, const char* name = 0); + void setSelected( bool selected ); + virtual QSize sizeHint() const; + +protected slots: + void slotKeyPressed(); + +signals: + void parentPleaseUpdate(); + +private: + RegExpWidget* _owner; +}; + +#endif diff --git a/kregexpeditor/singlecontainerwidget.cpp b/kregexpeditor/singlecontainerwidget.cpp new file mode 100644 index 0000000..4782dd9 --- /dev/null +++ b/kregexpeditor/singlecontainerwidget.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "singlecontainerwidget.moc" +#endif + +#include "singlecontainerwidget.h" +#include "concwidget.h" + +SingleContainerWidget::SingleContainerWidget(RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name) + : RegExpWidget( editorWindow, parent, name ) +{ +} + +bool SingleContainerWidget::updateSelection( bool parentSelected ) +{ + bool changed = RegExpWidget::updateSelection( parentSelected ); + changed = _child->updateSelection( _isSelected ) && changed; + if (changed) + repaint(); + + return changed; +} + +bool SingleContainerWidget::hasSelection() const +{ + return _isSelected || _child->hasSelection(); +} + +void SingleContainerWidget::clearSelection() +{ + _isSelected = false; + _child->clearSelection(); +} + +void SingleContainerWidget::deleteSelection() +{ + _child->deleteSelection(); + update(); +} + +void SingleContainerWidget::applyRegExpToSelection( RegExpType type ) +{ + _child->applyRegExpToSelection( type ); +} + +RegExp* SingleContainerWidget::selection() const +{ + if ( isSelected() ) + return regExp(); + else + return _child->selection(); +} + +bool SingleContainerWidget::validateSelection() const +{ + return _child->validateSelection(); +} + +QRect SingleContainerWidget::selectionRect() const +{ + if ( _isSelected ) + return QRect( mapToGlobal( QPoint(0,0) ), size() ); + else + return _child->selectionRect(); +} + +RegExpWidget* SingleContainerWidget::widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ) +{ + RegExpWidget* wid = _child->widgetUnderPoint( globalPos, justVisibleWidgets ); + if ( wid ) + return wid; + else { + // The child didn't contain the point, then lets see if this widget + // itself does. + return RegExpWidget::widgetUnderPoint( globalPos, justVisibleWidgets ); + } +} + +RegExpWidget* SingleContainerWidget::findWidgetToEdit( QPoint globalPos ) +{ + RegExpWidget* wid = _child->findWidgetToEdit( globalPos ); + if ( wid ) + return wid; + else if ( QRect(mapToGlobal(QPoint(0,0)), size()).contains( globalPos ) ) + return this; + else + return 0; +} + +void SingleContainerWidget::setConcChild( ConcWidget* conc ) +{ + delete _child; + _child = conc; +} + +void SingleContainerWidget::selectWidget( bool sel ) +{ + RegExpWidget::selectWidget( sel ); + _child->selectWidget( sel ); + update(); +} + +void SingleContainerWidget::updateAll() +{ + _child->updateAll(); + RegExpWidget::updateAll(); +} + +void SingleContainerWidget::updateCursorRecursively() +{ + _child->updateCursorRecursively(); + updateCursorShape(); +} + + diff --git a/kregexpeditor/singlecontainerwidget.h b/kregexpeditor/singlecontainerwidget.h new file mode 100644 index 0000000..8f07e6a --- /dev/null +++ b/kregexpeditor/singlecontainerwidget.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __singlecontainer +#define __singlecontainer +#include "regexpwidget.h" + +/** + Abstract class representing RegExp widgets having a single child. +*/ +class SingleContainerWidget :public RegExpWidget +{ +Q_OBJECT + +public: + SingleContainerWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + const char* name = 0); + + virtual bool updateSelection( bool parentSelected ); + virtual bool hasSelection() const; + virtual void clearSelection(); + virtual void deleteSelection(); + virtual void applyRegExpToSelection( RegExpType type ); + virtual RegExp* selection() const; + virtual bool validateSelection() const; + virtual QRect selectionRect() const; + virtual RegExpWidget* widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ); + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + virtual void setConcChild( ConcWidget* child ); + virtual void selectWidget( bool sel ); + virtual void updateAll(); + virtual void updateCursorRecursively(); + +protected: + ConcWidget *_child; +}; + + +#endif // __singlecontainer diff --git a/kregexpeditor/test-without-dl/Makefile.am b/kregexpeditor/test-without-dl/Makefile.am new file mode 100644 index 0000000..2162d09 --- /dev/null +++ b/kregexpeditor/test-without-dl/Makefile.am @@ -0,0 +1,8 @@ +check_PROGRAMS = regexptest +regexptest_SOURCES = main.cpp +regexptest_LDFLAGS = $(all_libraries) +regexptest_LDADD = ../libkregexpeditorgui.la $(LIB_KSYCOCA) +INCLUDES = $(all_includes) +KDE_CXXFLAGS = -g + +METASOURCES = AUTO diff --git a/kregexpeditor/test-without-dl/main.cpp b/kregexpeditor/test-without-dl/main.cpp new file mode 100644 index 0000000..54610ac --- /dev/null +++ b/kregexpeditor/test-without-dl/main.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <qfile.h> +#include "../kregexpeditorgui.h" +class ShootABug :public QObject +{ +public: + virtual bool eventFilter( QObject* recv, QEvent* event ) + { + if ( event->type() == QEvent::MouseButtonPress && + dynamic_cast<QMouseEvent*>(event)->state() == Qt::ControlButton ) { + // Ctrl + left mouse click. + + qDebug("----------------------------------------------------"); + qDebug((QString("Widget name : ") + QString( recv->name() )).latin1() ); + qDebug((QString("Widget class: ") + QString( recv->className() )).latin1() ); + qDebug("\nObject info:"); + recv->dumpObjectInfo(); + qDebug("\nObject tree:"); + recv->dumpObjectTree(); + qDebug("----------------------------------------------------"); + return false; + } + return false; + } +}; + +int main( int argc, char* argv[] ) +{ + KCmdLineArgs::init(argc, argv, "RegExp Example","",""); + KApplication myapp( argc, argv ); + + qApp->installEventFilter( new ShootABug() ); + + KRegExpEditorGUIDialog* iface = new KRegExpEditorGUIDialog( 0, "_editor", QStringList() ); + iface->setRegExp( QString::fromLatin1( "#include" ) ); + iface->doSomething( "setMinimal", (void*) false ); + iface->doSomething( "setSyntax", (void*) new QString( QString::fromLatin1( "Emacs" ) ) ); + iface->doSomething( "setShowSyntaxCombo", (bool*) true ); + + QFile file("/packages/kde-src/kdeutils/kregexpeditor/test/main.cpp"); + file.open(IO_ReadOnly); + QTextStream stream( &file); + QString txt = stream.read(); + iface->setMatchText( txt ); + + iface->exec(); +} + diff --git a/kregexpeditor/textrangeregexp.cpp b/kregexpeditor/textrangeregexp.cpp new file mode 100644 index 0000000..73c2923 --- /dev/null +++ b/kregexpeditor/textrangeregexp.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include <kmessagebox.h> +#endif + +#include "textrangeregexp.h" +#include "regexpconverter.h" + +TextRangeRegExp::TextRangeRegExp( bool selected ) : RegExp( selected ), + _negate(false), _digit(false), _nonDigit(false), _space(false), _nonSpace(false), _wordChar(false), _nonWordChar(false) +{ +} + +TextRangeRegExp::~TextRangeRegExp() +{ +} + + +void TextRangeRegExp::addCharacter( QString str ) +{ + _chars.append( str ); +} + +void TextRangeRegExp::addRange(QString from, QString to) +{ + _ranges.append( new StringPair( from, to ) ); +} + +bool TextRangeRegExp::check( ErrorMap&, bool, bool ) +{ + return false; +} + +QDomNode TextRangeRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit( "TextRange" ) ); + + if ( _negate ) + top.setAttribute( QString::fromLocal8Bit("negate"), true ); + if ( _digit ) + top.setAttribute( QString::fromLocal8Bit("digit"), true ); + if ( _nonDigit ) + top.setAttribute( QString::fromLocal8Bit("nonDigit"), true ); + if ( _space ) + top.setAttribute( QString::fromLocal8Bit("space"), true ); + if ( _nonSpace ) + top.setAttribute( QString::fromLocal8Bit("nonSpace"), true ); + if ( _wordChar ) + top.setAttribute( QString::fromLocal8Bit("wordChar"), true ); + if ( _nonWordChar ) + top.setAttribute( QString::fromLocal8Bit("nonWordChar"), true ); + + for ( QStringList::ConstIterator it = _chars.begin(); it != _chars.end(); ++it ) { + QDomElement elm = doc->createElement( QString::fromLocal8Bit( "Character" ) ); + elm.setAttribute( QString::fromLocal8Bit( "char" ), *it ); + top.appendChild( elm ); + } + + for ( QPtrListIterator<StringPair> it2(_ranges); *it2; ++it2 ) { + QDomElement elm = doc->createElement( QString::fromLocal8Bit( "Range" ) ); + elm.setAttribute( QString::fromLocal8Bit( "from" ), (*it2)->first() ); + elm.setAttribute( QString::fromLocal8Bit( "to" ), (*it2)->second() ); + top.appendChild( elm ); + } + return top; +} + +bool TextRangeRegExp::load( QDomElement top, const QString& /*version*/ ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "TextRange" ) ); + QString str; + QString one = QString::fromLocal8Bit("1"); + QString zero = QString::fromLocal8Bit("0"); + + str = top.attribute( QString::fromLocal8Bit("negate"), zero ); + _negate = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("digit"), zero ); + _digit = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("nonDigit"), zero ); + _nonDigit = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("space"), zero ); + _space = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("nonSpace"), zero ); + _nonSpace = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("wordChar"), zero ); + _wordChar = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("nonWordChar"), zero ); + _nonWordChar = ( str == one ); + + for ( QDomNode node = top.firstChild(); !node.isNull(); node = node.nextSibling() ) { + if ( !node.isElement() ) + continue; // Skip comments. + QDomElement child = node.toElement(); + + if ( child.tagName() == QString::fromLocal8Bit( "Character" ) ) { + QString ch = child.attribute( QString::fromLocal8Bit( "char" ) ); + addCharacter( ch ); + } + else if ( child.tagName() == QString::fromLocal8Bit( "Range" ) ) { + QString from = child.attribute( QString::fromLocal8Bit( "from" ) ); + QString to = child.attribute( QString::fromLocal8Bit( "to" ) ); + addRange( from, to ); + } + else { + KMessageBox::sorry( 0, i18n("<p>Invalid sub element to element <b>TextRange</b>. Tag was <b>%1</b></p>").arg(child.tagName()), + i18n("Error While Loading From XML File") ) ; + return false; + } + } + return true; +} + +bool TextRangeRegExp::operator==( const RegExp& other ) const +{ + return ( RegExpConverter::current()->toStr( const_cast<TextRangeRegExp*>( this ), false ) == + RegExpConverter::current()->toStr( const_cast<RegExp*>( &other ), false ) ); +} + diff --git a/kregexpeditor/textrangeregexp.h b/kregexpeditor/textrangeregexp.h new file mode 100644 index 0000000..de1785e --- /dev/null +++ b/kregexpeditor/textrangeregexp.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __TEXTRANGEREGEXP_H +#define __TEXTRANGEREGEXP_H + +#include "regexp.h" +#include "pair.h" +#include <qstringlist.h> + +typedef Pair<QString,QString> StringPair; + +/** + Abstract syntax node for `text range' regular expression + + @internal +*/ +class TextRangeRegExp :public RegExp +{ +public: + TextRangeRegExp( bool selected ); + virtual ~TextRangeRegExp(); + + void addCharacter( QString ch ); + QStringList chars() const { return _chars; } + void clearChars() { _chars.clear(); } + + void addRange( QString from, QString to ); + QPtrList<StringPair> range() const { return _ranges; } + void clearRange() { _ranges.clear(); } + + void setNegate( bool set ) { _negate = set; } + void setDigit( bool set ) { _digit = set; } + void setNonDigit( bool set ) { _nonDigit = set; } + void setSpace( bool set ) { _space = set; } + void setNonSpace( bool set ) { _nonSpace = set; } + void setWordChar( bool set ) { _wordChar = set; } + void setNonWordChar( bool set ) { _nonWordChar = set; } + + bool negate() const { return _negate; } + bool digit() const { return _digit; } + bool nonDigit() const { return _nonDigit; } + bool space() const { return _space; } + bool nonSpace() const { return _nonSpace; } + bool wordChar() const { return _wordChar; } + bool nonWordChar() const { return _nonWordChar; } + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return TEXTRANGE;} + virtual bool operator==( const RegExp& other ) const; + +private: + bool _negate, _digit, _nonDigit, _space, _nonSpace, _wordChar, _nonWordChar; + QStringList _chars; + QPtrList<StringPair> _ranges; +}; + +#endif // __TEXTRANGEREGEXP_H diff --git a/kregexpeditor/textregexp.cpp b/kregexpeditor/textregexp.cpp new file mode 100644 index 0000000..7d5d02c --- /dev/null +++ b/kregexpeditor/textregexp.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <kmessagebox.h> + #include <klocale.h> +#endif + +#include "textregexp.h" + +TextRegExp::TextRegExp( bool selected, QString text) :RegExp( selected ) +{ + _text = text; +} + +bool TextRegExp::check( ErrorMap&, bool, bool ) +{ + return false; +} + + +void TextRegExp::append( QString str ) +{ + _text.append( str ); +} + +QDomNode TextRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement(QString::fromLocal8Bit("Text")); + QDomText text = doc->createTextNode( _text ); + top.appendChild( text ); + return top; +} + +bool TextRegExp::load( QDomElement top, const QString& /*version*/) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Text" ) ); + if ( top.hasChildNodes() ) { + QDomNode child = top.firstChild(); + if ( ! child.isText() ) { + KMessageBox::sorry( 0, i18n("<p>Element <b>Text</b> did not contain any textual data.</p>"), + i18n("Error While Loading From XML File") ) ; + return false; + } + QDomText txtNode = child.toText(); + _text = txtNode.data(); + } + else { + _text = QString::fromLatin1( "" ); + } + + return true; +} + +bool TextRegExp::operator==( const RegExp& other ) const { + if ( other.type() != type() ) + return false; + + const TextRegExp& theOther = dynamic_cast<const TextRegExp&>( other ); + if ( text() == theOther.text() ) + return true; + + return false; +} + diff --git a/kregexpeditor/textregexp.h b/kregexpeditor/textregexp.h new file mode 100644 index 0000000..f98d0e9 --- /dev/null +++ b/kregexpeditor/textregexp.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __textregexp_h +#define __textregexp_h + +#include "regexp.h" + +/** + Abstract syntax node for `text' regular expression + @internal +*/ +class TextRegExp :public RegExp +{ +public: + TextRegExp( bool selected, QString text = QString::null); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { + if ( _text.length() > 1 ) + return 2; + else + return 4; + } + QString text() const { return _text; } + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + void append( QString str); + virtual RegExpType type() const { return TEXT;} + virtual bool operator==( const RegExp& other ) const; + +private: + QString _text; +}; + +#endif // __textregexp_h diff --git a/kregexpeditor/textwidget.cpp b/kregexpeditor/textwidget.cpp new file mode 100644 index 0000000..c36d1a8 --- /dev/null +++ b/kregexpeditor/textwidget.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "textwidget.moc" +#endif + +#include "textwidget.h" +#include "textregexp.h" +#include "selectablelineedit.h" +#include <qlayout.h> + +TextWidget::TextWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + :RegExpWidget(editorWindow, parent, name) +{ + init( QString::fromLocal8Bit("") ); +} + +TextWidget::TextWidget( TextRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + : RegExpWidget( editorWindow, parent, name ) +{ + init(regexp->text()); +} + +void TextWidget::init( const QString& txt ) +{ + QHBoxLayout *lay = new QHBoxLayout(this); + _edit = new SelectableLineEdit( this, this, "TextWidget::edit" ); + _edit->setDragEnabled( false ); //otherwise QLineEdit::mouseMoveEvent will set the cursor over and over again. + lay->addWidget(_edit); + + _edit->setText( txt ); + + connect( _edit, SIGNAL( parentPleaseUpdate() ), this, SLOT(slotUpdate()) ); + setFocusProxy( _edit ); + _edit->installEventFilter( this ); + connect( _edit, SIGNAL( textChanged( const QString & ) ), _editorWindow, SLOT( emitChange() ) ); +} + + +void TextWidget::slotUpdate() +{ + // I need to force the parent to repaint, as the size change of this + // widget may not be enough for the parent to change size, and in that + // case the parent would not repaint, and the text widget would not be + // resized. + QWidget *p = static_cast<QWidget*>(parent()); + if (p) + p->repaint(); + _editorWindow->updateContent( this ); +} + +QSize TextWidget::sizeHint() const +{ + return _edit->sizeHint(); +} + +void TextWidget::paintEvent( QPaintEvent *e) +{ + RegExpWidget::paintEvent(e); +} + +void TextWidget::selectWidget( bool sel ) +{ + _edit->setSelected( sel ); +} + +bool TextWidget::updateSelection(bool parentSelected) +{ + bool changed = RegExpWidget::updateSelection( parentSelected ); + + // I need to call this function all the time, else the rubber band will + // not be correctly deleted in the line edit. + _edit->setSelected( _isSelected ); + return changed; +} +void TextWidget::updateAll() +{ + _edit->update(); + update(); +} + +void TextWidget::clearSelection() +{ + _isSelected = false; + _edit->setSelected( false ); +} + +RegExp* TextWidget::regExp() const +{ + return new TextRegExp( isSelected(), _edit->text() ); +} + +bool TextWidget::eventFilter( QObject*, QEvent* event) +{ + // This is an event filter (in contrast to methods in SelectableLineEdit), + // otherwise lots of functions would need to be exported from TextWidget. + if ( event->type() == QEvent::MouseButtonRelease ) { + if ( _editorWindow->isInserting() ) { + if ( acceptWidgetInsert( _editorWindow->insertType() ) ) { + mouseReleaseEvent( static_cast<QMouseEvent*>(event) ); + } + return true; + } + } + else if ( event->type() == QEvent::MouseButtonPress ) { + if ( _editorWindow->isInserting() ) { + return true; + } + else if ( isSelected() ) { + QMouseEvent* e = static_cast<QMouseEvent*>( event ); + QMouseEvent ev( event->type(), mapTo(_editorWindow, e->pos()), + e->button(), e->state()); + QApplication::sendEvent( _editorWindow, &ev ); + return true; + } + } + + else if ( event->type() == QEvent::Enter ) { + if ( _editorWindow->isInserting() ) { + if ( acceptWidgetInsert( _editorWindow->insertType() ) ) { + _edit->setCursor(crossCursor); + } + else { + _edit->setCursor(forbiddenCursor); + } + } + else if ( isSelected() ) { + _edit->setCursor( arrowCursor ); + } + else { + _edit->setCursor( ibeamCursor ); + } + } + else if ( event->type() == QEvent::MouseButtonDblClick && _editorWindow->isInserting() ) { + return true; + } + return false; +} + + diff --git a/kregexpeditor/textwidget.h b/kregexpeditor/textwidget.h new file mode 100644 index 0000000..9a5c0be --- /dev/null +++ b/kregexpeditor/textwidget.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __textwidget +#define __textwidget + +#include "regexpwidget.h" +class SelectableLineEdit; +class TextRegExp; + +/** + RegExp widget representing text. + + @internal +*/ +class TextWidget : public RegExpWidget +{ + Q_OBJECT + +public: + TextWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + TextWidget( TextRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return TEXT; } + virtual void updateAll(); + virtual void selectWidget( bool ); + +protected: + void init( const QString& text ); + virtual void paintEvent( QPaintEvent *e ); + virtual bool updateSelection( bool parentSelected ); + virtual void clearSelection(); + virtual bool eventFilter( QObject*, QEvent* ); + +protected slots: + void slotUpdate(); + +private: + QString text; + SelectableLineEdit *_edit; + QSize textSize, boxSize, editSize; +}; + + + +#endif // __textwidget diff --git a/kregexpeditor/triple.h b/kregexpeditor/triple.h new file mode 100644 index 0000000..c44276c --- /dev/null +++ b/kregexpeditor/triple.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __triple_h +#define __triple_h + +/** + @internal +*/ +template<class F, class S, class T> class Triple +{ +public: + Triple() {}; + Triple(F first, S second, T third) : _first(first), _second(second), + _third(third) {} + F first() { return _first; } + S second() { return _second; } + T third() { return _third; } +private: + F _first; + S _second; + T _third; + +}; + +#endif // __triple_h diff --git a/kregexpeditor/userdefinedregexps.cpp b/kregexpeditor/userdefinedregexps.cpp new file mode 100644 index 0000000..de2f675 --- /dev/null +++ b/kregexpeditor/userdefinedregexps.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klineeditdlg.h> + #include <klocale.h> + #include <kmessagebox.h> + #include <kstandarddirs.h> + #include <kdebug.h> + #include "userdefinedregexps.moc" +#endif + +#include "userdefinedregexps.h" +#include <qheader.h> +#include <qpopupmenu.h> +#include <qdir.h> +#include "widgetfactory.h" +#include "compoundregexp.h" +#include <qlayout.h> +#include <qlabel.h> + +UserDefinedRegExps::UserDefinedRegExps( QWidget *parent, const char *name ) + : QDockWindow( QDockWindow::InDock, parent, name) +{ + QWidget* top = new QWidget( this ); + QVBoxLayout* lay = new QVBoxLayout( top, 6 ); + lay->setAutoAdd( true ); + + QLabel* label = new QLabel( i18n("Compound regular expressions:"), top ); + + // This is to avoid that the label set the minimum width for the window. + label->setMinimumSize(1,0); + + _userDefined = new QListView( top, "UserDefinedRegExps::_userDefined" ); + _userDefined->addColumn( QString::null ); + _userDefined->header()->hide(); + // _userDefined->setRootIsDecorated( true ); + setWidget( top ); + slotPopulateUserRegexps(); + + connect( _userDefined, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotLoad(QListViewItem*)) ); + connect( _userDefined, SIGNAL(rightButtonPressed(QListViewItem*,const QPoint&, int )), + this, SLOT( slotEdit( QListViewItem*, const QPoint& ) ) ); +} + +void UserDefinedRegExps::slotPopulateUserRegexps() +{ + _userDefined->clear(); + _regExps.clear(); + + createItems( i18n("User Defined"), WidgetWinItem::path(), true ); + +#ifdef QT_ONLY + QStringList dirs; + dirs << QString::fromLatin1( "predefined" ); +#else + QStringList dirs = KGlobal::dirs()->findDirs( "data", QString::fromLocal8Bit("kregexpeditor/predefined/") ); +#endif + + for ( QStringList::iterator it1 = dirs.begin(); it1 != dirs.end(); ++it1 ) { + QDir dir( *it1, QString::null, QDir::Name, QDir::Dirs ); + QStringList subdirs = dir.entryList(); + for ( QStringList::iterator it2 = subdirs.begin(); it2 != subdirs.end(); ++it2 ) { + if ( *it2 == QString::fromLocal8Bit(".") || *it2 == QString::fromLocal8Bit("..") ) + continue; + createItems( *it2, *it1 + QString::fromLocal8Bit("/") + *it2, false ); + } + } + +} + +void UserDefinedRegExps::createItems( const QString& _title, const QString& dir, bool usersRegExp ) +{ + QString title = _title; + if (_title == QString::fromLatin1("general")) + title = i18n("General"); + + QListViewItem* lvItem = new QListViewItem( _userDefined, title ); + lvItem->setOpen( true ); + + QDir directory( dir ); + QStringList files = directory.entryList( QString::fromLocal8Bit("*.regexp") ); + for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it ) { + QString fileName = dir + QString::fromLocal8Bit("/") + *it; + + QFile file( fileName ); + if ( ! file.open(IO_ReadOnly) ) { + KMessageBox::sorry( this, i18n("Could not open file for reading: %1").arg(fileName) ); + continue; + } + + QTextStream stream( &file ); + QString data = stream.read(); + file.close(); + + RegExp* regexp = WidgetFactory::createRegExp( data ); + if ( ! regexp ) { + KMessageBox::sorry( this, i18n("File %1 containing user defined regular expression contained an error").arg( fileName ) ); + continue; + } + + new WidgetWinItem( *it, regexp, usersRegExp, lvItem ); + + // Insert the regexp into the list of compound regexps + if ( regexp->type() == RegExp::COMPOUND ) { + CompoundRegExp* cregexp = dynamic_cast<CompoundRegExp*>( regexp ); + if ( cregexp && cregexp->allowReplace() ) + _regExps.append( cregexp ); + } + } +} + +const QPtrList<CompoundRegExp> UserDefinedRegExps::regExps() const +{ + return _regExps; +} + + +void UserDefinedRegExps::slotUnSelect() +{ + _userDefined->clearSelection(); +} + +void UserDefinedRegExps::slotLoad(QListViewItem* item) +{ + if ( !item || ! dynamic_cast<WidgetWinItem*>(item) ) { + // Mouse pressed outside a widget. + return; + } + + WidgetWinItem* wwi = dynamic_cast<WidgetWinItem*>(item); + if (wwi) { + emit load( wwi->regExp() ); + } +} + +void UserDefinedRegExps::slotEdit( QListViewItem* item, const QPoint& pos ) +{ + QPopupMenu* menu = new QPopupMenu( this ); + menu->insertItem(i18n("Delete"), 1 ); + menu->insertItem(i18n("Rename..."), 2 ); + if ( !item || ! dynamic_cast<WidgetWinItem*>( item ) ) { + // menu not selected on an item + menu->setItemEnabled( 1, false ); + menu->setItemEnabled( 2, false ); + } + else { + // Only allow rename and delete of users own regexps. + WidgetWinItem* winItem = dynamic_cast<WidgetWinItem*>( item ); + if ( winItem && ! winItem->isUsersRegExp() ) { + menu->setItemEnabled( 1, false ); + menu->setItemEnabled( 2, false ); + } + } + + int which = menu->exec( pos ); + + if ( which == 1 ) { // Delete + WidgetWinItem* winItem = dynamic_cast<WidgetWinItem*>( item ); + Q_ASSERT( winItem ); + QFile file( winItem->fileName() ); + Q_ASSERT( file.exists() ); + file.remove(); + delete item; + } + else if ( which == 2 ) { // Rename + WidgetWinItem* winItem = dynamic_cast<WidgetWinItem*>( item ); + Q_ASSERT( winItem ); + + QString oldFile = winItem->fileName(); + QString oldName = winItem->name(); + + QString txt; +#ifdef QT_ONLY + txt = QInputDialog::getText( tr("Rename Regular Expression"), tr("New name:") ); +#else + KLineEditDlg dlg(i18n("New name:"), oldName, this); + dlg.setCaption(i18n("Rename Item")); + bool ok = dlg.exec(); + if ( ok ) + txt = dlg.text(); +#endif + if ( !txt.isNull() && oldName != txt ) { + QString fileName = WidgetWinItem::path() + QString::fromLocal8Bit("/") + txt + QString::fromLocal8Bit(".regexp"); + QFileInfo finfo( fileName ); + if ( finfo.exists() ) { + int answer = KMessageBox::warningYesNo( this, i18n("<p>Overwrite named regular expression <b>%1</b>?</p>").arg(txt), QString::null, i18n("Overwrite"), i18n("Do Not Overwrite") ); + if ( answer != KMessageBox::Yes ) + return; + + // An item with this name already exists. + delete winItem; + } + else + winItem->setName( txt ); + QDir dir; + dir.rename( oldFile, fileName ); + } + } + + + delete menu; +} + +void UserDefinedRegExps::slotSelectNewAction() +{ + slotUnSelect(); +} + +WidgetWinItem::WidgetWinItem( QString fileName, RegExp* regexp, bool usersRegExp, QListViewItem* parent ) + :QListViewItem( parent ), _regexp( regexp ), _usersRegExp ( usersRegExp ) +{ + int index = fileName.findRev(QString::fromLocal8Bit(".regexp")); + _name = fileName.left(index); + + setText( 0, _name ); +} + +QString WidgetWinItem::fileName() const +{ + return path() + QString::fromLocal8Bit("/") +_name + QString::fromLocal8Bit(".regexp"); +} + +RegExp* WidgetWinItem::regExp() const +{ + return _regexp; +} + +QString WidgetWinItem::name() const +{ + return _name; +} + +void WidgetWinItem::setName( const QString& nm ) +{ + _name = nm; + setText( 0, nm ); +} + +QString WidgetWinItem::path() +{ +#ifdef QT_ONLY + return QString::fromLatin1( "predefined" ); +#else + return locateLocal("data", QString::fromLocal8Bit("KRegExpEditor/")); +#endif +} + + + diff --git a/kregexpeditor/userdefinedregexps.h b/kregexpeditor/userdefinedregexps.h new file mode 100644 index 0000000..358aa73 --- /dev/null +++ b/kregexpeditor/userdefinedregexps.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __USERDEFINEDREGEXPS_H +#define __USERDEFINEDREGEXPS_H +#include <qdockwindow.h> +#include <qlistview.h> + +#include "compoundregexp.h" + +class QPoint; +class RegExp; + +class UserDefinedRegExps :public QDockWindow +{ +Q_OBJECT + +public: + UserDefinedRegExps( QWidget *parent, const char *name = 0 ); + const QPtrList<CompoundRegExp> regExps() const; + +public slots: + void slotSelectNewAction(); + +protected slots: + void slotLoad(QListViewItem* item); + void slotEdit( QListViewItem* item, const QPoint& pos ); + void slotPopulateUserRegexps(); + void slotUnSelect(); + +protected: + void createItems( const QString& title, const QString& dir, bool usersRegExp ); + +signals: + void load( RegExp* ); + +private: + QListView* _userDefined; + QPtrList<CompoundRegExp> _regExps; +}; + +class WidgetWinItem :public QListViewItem +{ +public: + WidgetWinItem( QString name, RegExp* regexp, bool users, QListViewItem* parent ); + static QString path(); + + QString fileName() const; + RegExp* regExp() const; + QString name() const; + void setName( const QString& ); + bool isUsersRegExp() const { return _usersRegExp; } + +private: + QString _name; + RegExp* _regexp; + bool _usersRegExp; +}; + + +#endif // __USERDEFINEDREGEXPS_H diff --git a/kregexpeditor/util.cpp b/kregexpeditor/util.cpp new file mode 100644 index 0000000..8bff5de --- /dev/null +++ b/kregexpeditor/util.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "util.h" +#include <kiconloader.h> +#include <kstandarddirs.h> +QPixmap Util::getKRegExpEditorIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage(name) ); + return pix; +#else + return KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/") +name ), + KIcon::Toolbar ); +#endif +} + +QPixmap Util::getSystemIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( name ) ); + return pix; +#else + KIconLoader loader; + return loader.loadIcon( name, KIcon::Toolbar); +#endif + +} + +QIconSet Util::getSystemIconSet( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( name ) ); + return QIconSet( pix ); +#else + KIconLoader loader; + return loader.loadIconSet( name, KIcon::Toolbar); +#endif + +} diff --git a/kregexpeditor/util.h b/kregexpeditor/util.h new file mode 100644 index 0000000..a3b406e --- /dev/null +++ b/kregexpeditor/util.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef UTIL_H +#define UTIL_H + +#include <qpixmap.h> +#include <qiconset.h> + +class Util +{ +public: + static QPixmap getKRegExpEditorIcon( const QString& name ); + static QPixmap getSystemIcon( const QString& name ); + static QIconSet getSystemIconSet( const QString& name ); +}; + +#endif // UTIL_H + diff --git a/kregexpeditor/verifier.cpp b/kregexpeditor/verifier.cpp new file mode 100644 index 0000000..322db12 --- /dev/null +++ b/kregexpeditor/verifier.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> + #include "verifier.moc" +#endif + +#include "verifier.h" + +Verifier::Verifier( QWidget* parent, const char* name ) : QTextEdit( parent, name ) + /* QT_ANCHOR_DO_NOT_WORK: ,_current( 0 ) */ +{ + _highlighter = 0; + setMinimumSize(1,1); +} + +/** + Update text edit to show matches of regular expression +*/ +void Verifier::verify( const QString& reg ) +{ + if ( _highlighter ) { + _highlighter->setRegExp( reg ); + _highlighter->rehighlight(); + } +} + + +/** + Make the text edit display the text without any matches. +*/ +void Verifier::clearRegexp() +{ + if ( _highlighter ) { + _highlighter->setRegExp( QString::null ); + _highlighter->rehighlight(); + } +} + +/** + Set case sensitive matching +*/ +void Verifier::setCaseSensitive( bool b ) +{ + if ( _highlighter ) + _highlighter->setCaseSensitive( b ); +} + + +/** + set minimal mathcing +*/ +void Verifier::setMinimal( bool b ) +{ + if ( _highlighter ) + _highlighter->setMinimal( b ); +} + +// Qt anchors do not work for <pre>...</pre>, thefore scrolling to next/prev match +// do not work. Enable this when they work. +// void Verifier::gotoFirst() +// { +// gotoNum(1); +// } +// +// void Verifier::gotoLast() +// { +// gotoNum( _count-1 ); +// } +// +// void Verifier::gotoPrev() +// { +// gotoNum( _current-1 ); +// } +// +// void Verifier::gotoNext() +// { +// gotoNum( _current+1 ); +// } +// +// void Verifier::gotoNum( int which ) +// { +// QString anchor = QString::fromLatin1("match%1").arg(which); +// scrollToAnchor( anchor ); +// _current = which; +// emit currentChanged( _current ); +// emit goBackwardPossible( which != 0 ); +// emit goForwardPossible( which != _count -1 ); +// } + + +void Verifier::setHighlighter( RegexpHighlighter* highlighter ) +{ + delete _highlighter; + _highlighter = highlighter; + setEnabled( _highlighter != 0 ); + +} + + diff --git a/kregexpeditor/verifier.h b/kregexpeditor/verifier.h new file mode 100644 index 0000000..661abef --- /dev/null +++ b/kregexpeditor/verifier.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef VERIFIER_H +#define VERIFIER_H +#include <qtextedit.h> +#include "regexphighlighter.h" +class QTimer; +class QProgressDialog; +class QLabel; +class SyntaxHighlighter; +class Verifier :public QTextEdit +{ +Q_OBJECT +public: + Verifier( QWidget* parent, const char* name = 0 ); + void setHighlighter( RegexpHighlighter* ); + +public slots: + void verify( const QString& regexp ); + void clearRegexp(); + void setCaseSensitive( bool ); + void setMinimal( bool ); + + // I have no way of telling the current paragrahp when highlighting - thefore scrolling to next/prev match + // do not work. Enable this when they work. + // void gotoFirst(); + // void gotoPrev(); + // void gotoNext(); + // void gotoLast(); + //signals: + // void countChanged( int ); + // void currentChanged( int ); + // void goBackwardPossible( bool ); + // void goForwardPossible( bool ); + + // protected: + // void gotoNum( int ); + +private: + int _count; + // int _current; + RegexpHighlighter* _highlighter; + +}; + +#endif // VERIFIER_H diff --git a/kregexpeditor/verifybuttons.cpp b/kregexpeditor/verifybuttons.cpp new file mode 100644 index 0000000..cd1b1ef --- /dev/null +++ b/kregexpeditor/verifybuttons.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY +#include "compat.h" +#include <qfiledialog.h> +#include "images.h" +#else +#include <klocale.h> +#include "verifybuttons.moc" +#include <kstandarddirs.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#endif + +#include "verifybuttons.h" +#include <qtooltip.h> +#include <qlayout.h> +#include <qwhatsthis.h> +#include "qtregexpconverter.h" +#include "emacsregexpconverter.h" +#include <qtoolbutton.h> +#include "util.h" +#include <qpopupmenu.h> +#include <qaction.h> + +VerifyButtons::VerifyButtons( QWidget* parent, const char* name ) + :QDockWindow( QDockWindow::InDock, parent, name ), _configMenu( 0 ) +{ + QBoxLayout* layout = boxLayout(); + + _verify = new QToolButton(this); + QIconSet icon = Util::getSystemIconSet( QString::fromLatin1("spellcheck")); + _verify->setIconSet( icon ); + QToolTip::add( _verify, i18n( "Verify regular expression" ) ); + QWhatsThis::add( _verify, i18n("Shows what part of the regular expression is being matched in the <i>verifier window</i>." + "(The window below the graphical editor window).")); + layout->addWidget( _verify ); + connect( _verify, SIGNAL( clicked() ), this, SIGNAL( verify() ) ); + + QToolButton* button = new QToolButton(this); + button->setPixmap( Util::getSystemIcon( QString::fromLatin1("fileopen")) ); + layout->addWidget( button ); + connect(button, SIGNAL(clicked()), this, SLOT(loadText())); + QToolTip::add( button, i18n("Load text in the verifier window") ); + + button = new QToolButton(this); + button->setPixmap( Util::getSystemIcon( QString::fromLatin1("package_settings")) ); + layout->addWidget( button ); + connect(button, SIGNAL(clicked()), this, SLOT(configure())); + QToolTip::add( button, i18n("Settings") ); + + // It is currently not possible to ask for the paragraph being highlighted, thefore scrolling to next/prev match + // do not work. Enable this when they work. + // _first = new QToolButton( QString::fromLatin1("<<"), this); + // layout->addWidget( _first ); + // connect(_first, SIGNAL(clicked()), this, SIGNAL( gotoFirst())); + // _first->setFixedWidth( 25 ); + // + // _prev = new QToolButton(QString::fromLatin1("<"), this); + // layout->addWidget( _prev ); + // connect(_prev, SIGNAL(clicked()), this, SIGNAL( gotoPrev())); + // _prev->setFixedWidth( 20 ); + // + // _next = new QToolButton(QString::fromLatin1(">"), this); + // layout->addWidget( _next ); + // connect(_next, SIGNAL(clicked()), this, SIGNAL( gotoNext())); + // _next->setFixedWidth( 20 ); + // + // _last = new QToolButton(QString::fromLatin1(">>"), this); + // layout->addWidget( _last ); + // connect(_last, SIGNAL(clicked()), this, SIGNAL( gotoLast())); + // _last->setFixedWidth( 25 ); + + // Same as above +// QLabel* label = new QLabel( i18n("Matches: "), this ); +// layout->addWidget( label ); +// _matches = new QLabel(i18n("-"), this ); +// layout->addWidget( _matches ); +// QString txt = i18n( "Shows number of times regular expression matches the text in the verifier window"); +// QToolTip::add( label, txt ); +// QToolTip::add( _matches, txt ); + + _verify->setEnabled( false ); + + // -------------------------------------------------- RegExp Converters + + // Qt + RegExpConverter* converter = new QtRegExpConverter(); + _converters.append( qMakePair( converter, static_cast<QAction*>( 0 ) ) ); + QString qtConverterName = converter->name(); + + // Emacs + converter = new EmacsRegExpConverter(); + _converters.append( qMakePair( converter, static_cast<QAction*>( 0 ) ) ); + + + // -------------------------------------------------- Initialize the config menu + _configMenu = new QPopupMenu( this, "config menu" ); + + // Auto Verify + QAction* autoVerify = new QAction( i18n("Verify on the Fly"), 0, this ); + autoVerify->setToggleAction( true ); + autoVerify->setOn( true ); + connect( autoVerify, SIGNAL( toggled( bool ) ), this, SLOT( updateVerifyButton( bool ) ) ); + connect( autoVerify, SIGNAL( toggled( bool ) ), this, SIGNAL( autoVerify( bool ) ) ); + autoVerify->addTo( _configMenu ); + autoVerify->setToolTip( i18n( "Toggle on-the-fly verification of regular expression" ) ); + autoVerify->setWhatsThis( i18n( "Enabling this option will make the verifier update for each edit. " + "If the verify window contains much text, or if the regular expression is either " + "complex or matches a lot of time, this may be very slow.")); + + // RegExp Languages + QPopupMenu* languages = new QPopupMenu( _configMenu ); + _languageId = _configMenu->insertItem( i18n("RegExp Language"), languages ); + + QActionGroup* grp = new QActionGroup( this ); + for( QValueList< QPair<RegExpConverter*,QAction*> >::Iterator it = _converters.begin(); it != _converters.end(); ++it ) { + QString name = (*it).first->name(); + QAction* action = new QAction( name, 0, this ); + action->setToggleAction( true ); + grp->add( action ); + (*it).second = action; + } + grp->addTo( languages ); + connect( grp, SIGNAL( selected( QAction* ) ), this, SLOT( slotChangeSyntax( QAction* ) ) ); + _configMenu->setItemEnabled( _languageId, false ); + + // Select the Qt converter by default + setSyntax( qtConverterName ); +} + + + +void VerifyButtons::updateVerifyButton( bool b ) +{ + _verify->setEnabled( !b ); +} + +void VerifyButtons::loadText() +{ + QString fileName = KFileDialog::getOpenFileName(QString::null, QString::null, this); + if ( !fileName.isNull() ) { + emit loadVerifyText( fileName ); + } +} + +// Qt anchors do not work for <pre>...</pre>, thefore scrolling to next/prev match +// do not work. Enable this when they work. +// void VerifyButtons::enableBackwardButtons( bool b ) +// { +// _first->setEnabled( b ); +// _prev->setEnabled( b ); +// } +// +// void VerifyButtons::enableForwardButtons( bool b ) +// { +// _next->setEnabled( b ); +// _last->setEnabled( b ); +// } + +void VerifyButtons::setMatchCount( int /*count*/ ) +{ +// currently this is not possible due to limitation in QSyntaxHighlighter +/* + if ( count == -1 ) + _matches->setText( QString::fromLatin1("-") ); + else + _matches->setText( QString::number( count ) ); +*/ +} + +void VerifyButtons::slotChangeSyntax( QAction* action ) +{ + emit changeSyntax( action->menuText() ); +} + +RegExpConverter* VerifyButtons::setSyntax( const QString& which) +{ + for( QValueList< QPair<RegExpConverter*, QAction*> >::Iterator it = _converters.begin(); it != _converters.end(); ++it ) { + QString name = (*it).first->name(); + if ( name == which ) { + (*it).second->setOn( true ); + return (*it).first; + } + } + qWarning( "No such converter: '%s'", which.latin1() ); + return 0; +} + +void VerifyButtons::configure() +{ + _configMenu->exec( QCursor::pos() ); +} + +void VerifyButtons::setAllowNonQtSyntax( bool b ) +{ + _configMenu->setItemEnabled( _languageId, b ); +} diff --git a/kregexpeditor/verifybuttons.h b/kregexpeditor/verifybuttons.h new file mode 100644 index 0000000..aaf3593 --- /dev/null +++ b/kregexpeditor/verifybuttons.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef VERIFYBUTTONS_H +#define VERIFYBUTTONS_H + +#include <qdockwindow.h> +#include "regexpconverter.h" +class QToolButton; +class QLabel; +class QAction; +class QPopupMenu; + +class VerifyButtons :public QDockWindow +{ + Q_OBJECT + +public: + VerifyButtons( QWidget* parent, const char* name ); + RegExpConverter* setSyntax( const QString& ); + void setAllowNonQtSyntax( bool ); + +signals: + void verify(); + void autoVerify( bool ); + void loadVerifyText( const QString& ); + + // Qt anchors do not work for <pre>...</pre>, thefore scrolling to next/prev match + // do not work. Enable this when they work. + // void gotoFirst(); + // void gotoPrev(); + // void gotoNext(); + // void gotoLast(); + + void changeSyntax( const QString& ); + +public slots: + // void enableForwardButtons( bool ); + // void enableBackwardButtons( bool ); + void setMatchCount( int ); + +protected slots: + void updateVerifyButton( bool ); + void loadText(); + void slotChangeSyntax( QAction* action ); + void configure(); + +private: + QToolButton* _verify; + QLabel* _matches; + QPopupMenu* _configMenu; + int _languageId; + + // Qt anchors do not work for <pre>...</pre>, thefore scrolling to next/prev match + // do not work. Enable this when they work. + // QToolButton* _first; + // QToolButton* _prev; + // QToolButton* _next; + // QToolButton* _last; + + QValueList< QPair<RegExpConverter*,QAction*> > _converters; +}; + + +#endif // VERIFYBUTTONS_H diff --git a/kregexpeditor/widgetfactory.cpp b/kregexpeditor/widgetfactory.cpp new file mode 100644 index 0000000..e2e860d --- /dev/null +++ b/kregexpeditor/widgetfactory.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include <kmessagebox.h> +#endif + +#include "widgetfactory.h" +#include "repeatwidget.h" +#include "textwidget.h" +#include "characterswidget.h" +#include "altnwidget.h" +#include "zerowidgets.h" +#include "compoundwidget.h" +#include "concwidget.h" +#include "lookaheadwidget.h" + +#include "textregexp.h" +#include "textrangeregexp.h" +#include "repeatregexp.h" +#include "lookaheadregexp.h" +#include "concregexp.h" +#include "altnregexp.h" +#include "positionregexp.h" +#include "dotregexp.h" +#include "kregexpeditorgui.h" + +bool WidgetFactory::isContainer( RegExpType tp ) +{ + return ( tp == REPEAT || tp == ALTN || tp == COMPOUND ); +} + +RegExpWidget* WidgetFactory::createWidget( RegExpEditorWindow* win, QWidget* parent, + RegExpType type ) +{ + RegExpWidget* widget = 0; + + switch (type) { + case TEXT: + return new TextWidget( win, parent ); break; + case ALTN: + return new AltnWidget( win, parent ); break; + case DOT: + return new AnyCharWidget( win, parent ); break; + case BEGLINE: + return new BegLineWidget( win, parent ); break; + case ENDLINE: + return new EndLineWidget( win, parent ); break; + case WORDBOUNDARY: + return new WordBoundaryWidget( win, parent ); break; + case NONWORDBOUNDARY: + return new NonWordBoundaryWidget( win, parent ); break; + case POSLOOKAHEAD: + case NEGLOOKAHEAD: + return new LookAheadWidget( win, type, parent ); break; + case REPEAT: + widget = new RepeatWidget( win, parent ); break; + case CHARSET: + widget = new CharactersWidget( win, parent ); break; + case COMPOUND: + widget = new CompoundWidget( win, parent ); break; + default: + qFatal("It should not be possible to get here!"); + return 0; + } + + if ( widget->edit() == QDialog::Rejected ) { + delete widget; + return 0; + } + return widget; +} + +RegExpWidget* WidgetFactory::createWidget( RegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent ) +{ + if ( regexp == 0 ) { + qFatal("%s:%d Regexp is 0", __FILE__, __LINE__ ); + } + else if ( TextRegExp* reg = dynamic_cast<TextRegExp*>( regexp ) ) + return new TextWidget( reg, editorWindow, parent ); + else if ( TextRangeRegExp* reg = dynamic_cast<TextRangeRegExp*>( regexp ) ) + return new CharactersWidget( reg, editorWindow, parent ); + else if ( RepeatRegExp* reg = dynamic_cast<RepeatRegExp*>( regexp ) ) + return new RepeatWidget( reg, editorWindow, parent ); + else if ( LookAheadRegExp* reg = dynamic_cast<LookAheadRegExp*>( regexp ) ) { + if ( reg->lookAheadType() == LookAheadRegExp::POSITIVE ) + return new LookAheadWidget( reg, editorWindow, POSLOOKAHEAD, parent ); + else + return new LookAheadWidget( reg, editorWindow, NEGLOOKAHEAD, parent ); + } + else if ( ConcRegExp* reg = dynamic_cast<ConcRegExp*>( regexp ) ) + return new ConcWidget( reg, editorWindow, parent ); + else if ( AltnRegExp* reg = dynamic_cast<AltnRegExp*>( regexp ) ) + return new AltnWidget( reg, editorWindow, parent ); + else if ( PositionRegExp* reg = dynamic_cast<PositionRegExp*>( regexp ) ) { + switch ( reg->position() ) { + case PositionRegExp::BEGLINE: + return new BegLineWidget( editorWindow, parent ); + case PositionRegExp::ENDLINE: + return new EndLineWidget( editorWindow, parent ); + case PositionRegExp::WORDBOUNDARY: + return new WordBoundaryWidget( editorWindow, parent ); + case PositionRegExp::NONWORDBOUNDARY: + return new NonWordBoundaryWidget( editorWindow, parent ); + } + } + else if ( dynamic_cast<DotRegExp*>( regexp ) ) + return new AnyCharWidget( editorWindow, parent ); + else if ( CompoundRegExp* reg = dynamic_cast<CompoundRegExp*>( regexp ) ) + return new CompoundWidget( reg, editorWindow, parent ); + else { + qFatal("%s:%d Internal Error: Unknown RegExp type", __FILE__, __LINE__); + } + return 0; +} + +RegExp* WidgetFactory::createRegExp( QDomElement node, const QString& version ) +{ + QString tag = node.tagName(); + RegExp* regexp; + if ( tag == QString::fromLocal8Bit( "TextRange" ) ) + regexp = new TextRangeRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Text" ) ) + regexp = new TextRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Concatenation" ) ) + regexp = new ConcRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Alternatives" ) ) + regexp = new AltnRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "BegLine" ) ) + regexp = new PositionRegExp( false, PositionRegExp::BEGLINE ); + else if ( tag == QString::fromLocal8Bit( "EndLine" ) ) + regexp = new PositionRegExp( false, PositionRegExp::ENDLINE ); + else if ( tag == QString::fromLocal8Bit( "WordBoundary" ) ) + regexp = new PositionRegExp( false, PositionRegExp::WORDBOUNDARY ); + else if ( tag == QString::fromLocal8Bit( "NonWordBoundary" ) ) + regexp = new PositionRegExp( false, PositionRegExp::NONWORDBOUNDARY ); + else if ( tag == QString::fromLocal8Bit( "PositiveLookAhead" ) ) + regexp = new LookAheadRegExp( false, LookAheadRegExp::POSITIVE ); + else if ( tag == QString::fromLocal8Bit( "NegativeLookAhead" ) ) + regexp = new LookAheadRegExp( false, LookAheadRegExp::NEGATIVE ); + else if ( tag == QString::fromLocal8Bit( "Compound" ) ) + regexp = new CompoundRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "AnyChar" ) ) + regexp = new DotRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Repeat" ) ) + regexp = new RepeatRegExp( false ); + else { + KMessageBox::sorry( 0, i18n("<p>Unknown tag while reading XML. Tag was <b>%1</b></p>").arg(tag), + i18n("Error While Loading From XML File") ) ; + + return 0; + } + + bool ok = regexp->load( node, version ); + if (ok) + return regexp; + else { + delete regexp; + return 0; + } + return 0; +} + +RegExp* WidgetFactory::createRegExp( QString str ) +{ + QDomDocument doc; + bool ok = doc.setContent( str ); + if ( !ok ) { + KMessageBox::sorry( 0, i18n("Error while loading regular expression from XML. Most probably the regular expression had unmatched tags."), + i18n("Error While Loading Regular Expression From XML") ) ; + } + + + // Read the RegularExpression element, and extract the version. + QDomElement top = doc.documentElement(); + if (! (top.tagName() == QString::fromLocal8Bit("RegularExpression")) ) { + KMessageBox::sorry( 0, i18n("<p>XML file did not contain a <b>%1</b> tag.</p>").arg(QString::fromLatin1("RegularExpression")), + i18n("Error While Loading From XML File") ) ; + } + QString version = top.attribute( QString::fromLocal8Bit("version"), KRegExpEditorGUI::version ); + QDomNode child = top.firstChild(); + if ( ! child.isElement() ) { + KMessageBox::sorry( 0, i18n("<p>Error while reading XML file. The element just below the tag " + "<b>%1</b> was not an element.</p>").arg(QString::fromLatin1("RegularExpression")), + i18n("Error While Loading From XML File") ) ; + } + + RegExp* regexp = WidgetFactory::createRegExp( child.toElement(), version ); + + return regexp; +} + diff --git a/kregexpeditor/widgetfactory.h b/kregexpeditor/widgetfactory.h new file mode 100644 index 0000000..b1d1f26 --- /dev/null +++ b/kregexpeditor/widgetfactory.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef widgetfactory +#define widgetfactory + +#include <qdom.h> + +class RegExpWidget; +class RegExpEditorWindow; +class QWidget; +class ConcWidget; +class RegExp; + +/** + All the different regular expression types. +*/ +enum RegExpType { + TEXT = 0, CHARSET = 1, DOT = 2, REPEAT = 3, ALTN = 4, COMPOUND = 5, BEGLINE = 6, + ENDLINE = 7, WORDBOUNDARY = 8, NONWORDBOUNDARY = 9, CONC = 10, DRAGACCEPTER = 11, + POSLOOKAHEAD = 12, NEGLOOKAHEAD = 13 +}; + +/** + Class used to encapsulate information about widgets. + + When reading widgets from a stream, it is necessary to know about all + sub-widgets to the @ref RegExpWidget class. This class exists to make + sure that such general information is only kept once. + + @internal +*/ +class WidgetFactory +{ +public: + static RegExpWidget* createWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + RegExpType type ); + static RegExpWidget* createWidget( RegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent ); + static RegExp* createRegExp( QDomElement node, const QString& version ); + static RegExp* createRegExp( QString str ); + static bool isContainer( RegExpType ); +}; + +#endif // widgetfactory + diff --git a/kregexpeditor/zerowidgets.cpp b/kregexpeditor/zerowidgets.cpp new file mode 100644 index 0000000..94a15d5 --- /dev/null +++ b/kregexpeditor/zerowidgets.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include <klocale.h> +#endif + +#include "zerowidgets.h" +#include "dotregexp.h" +#include "positionregexp.h" +#include <qpainter.h> +#include "myfontmetrics.h" +//-------------------------------------------------------------------------------- +// ZeroWidget +//-------------------------------------------------------------------------------- +ZeroWidget::ZeroWidget(QString txt, RegExpEditorWindow* editorWindow, + QWidget *parent, const char *name) + : RegExpWidget(editorWindow, parent, name ? name : "ZeroWidget" ) +{ + _text = txt; +} + +void ZeroWidget::addNewChild(DragAccepter *, RegExpWidget *) +{ + qFatal("No children should be added to this widget!"); +} + +QSize ZeroWidget::sizeHint() const +{ + QFontMetrics metrics = fontMetrics(); + _textSize = HackCalculateFontSize( metrics, _text ); + // _textSize = metrics.size(0,_text); + _boxSize = QSize(_textSize.width() + 2*space, _textSize.height() + 2 *space); + return _boxSize; +} + +void ZeroWidget::paintEvent( QPaintEvent *e) +{ + // So what is my Size? + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize); + + // Write the text and the rectangle + painter.drawText(space, space, _textSize.width(), _textSize.height(), 0, _text); + painter.drawRoundRect(0, 0, _boxSize.width(), _boxSize.height()); + + RegExpWidget::paintEvent(e); +} + + +//-------------------------------------------------------------------------------- +// AnyCharWidget +//-------------------------------------------------------------------------------- +AnyCharWidget::AnyCharWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Any\nCharacter"), editorWindow, parent, + name ? name : "AnyCharWidget") +{ +} + +RegExp* AnyCharWidget::regExp() const +{ + return new DotRegExp( isSelected() ); +} + + +//-------------------------------------------------------------------------------- +// BegLineWidget +//-------------------------------------------------------------------------------- +BegLineWidget::BegLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Line\nStart"), editorWindow, parent, + name ? name : "BegLineWidget") +{ +} + +RegExp* BegLineWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::BEGLINE ); + +} + +//-------------------------------------------------------------------------------- +// EndLineWidget +//-------------------------------------------------------------------------------- +EndLineWidget::EndLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Line\nEnd"), editorWindow, parent, name) +{ +} + +RegExp* EndLineWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::ENDLINE ); +} + +//-------------------------------------------------------------------------------- +// WordBoundaryWidget +//-------------------------------------------------------------------------------- +WordBoundaryWidget::WordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Word\nBoundary"), editorWindow, parent, + name ? name : "WordBoundaryWidget" ) +{ +} + +RegExp* WordBoundaryWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::WORDBOUNDARY ); +} + +//-------------------------------------------------------------------------------- +// NonWordBoundaryWidget +//-------------------------------------------------------------------------------- +NonWordBoundaryWidget::NonWordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Non-word\nBoundary"), editorWindow, parent, + name ? name : "NonWordBoundaryWidget" ) +{ +} + +RegExp* NonWordBoundaryWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::NONWORDBOUNDARY ); +} + diff --git a/kregexpeditor/zerowidgets.h b/kregexpeditor/zerowidgets.h new file mode 100644 index 0000000..cd5e9be --- /dev/null +++ b/kregexpeditor/zerowidgets.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen <blackie@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef zerowidget +#define zerowidget + +#include "regexpwidget.h" + +/** + Represents any widget in the regular expression dialog, which do not have sub widget. + @internal +*/ +class ZeroWidget :public RegExpWidget +{ +public: + ZeroWidget(QString text, RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + virtual QSize sizeHint() const; + +protected: + virtual void paintEvent( QPaintEvent *e ); + +private: + QString _text; + + mutable QSize _textSize; + mutable QSize _boxSize; +}; + + + +/** + RegExp widget for `any single character' + @internal +*/ +class AnyCharWidget :public ZeroWidget +{ +public: + AnyCharWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + + virtual RegExp* regExp() const; + virtual RegExpType type() const { return DOT; } +}; + + + + +/** + RegExp widget for `beginning of line' + @internal +*/ +class BegLineWidget : public ZeroWidget +{ +public: + BegLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return BEGLINE; } +}; + + + + +/** + RegExp widget for `end of line' + @internal +*/ +class EndLineWidget : public ZeroWidget +{ +public: + EndLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return ENDLINE; } +}; + + + +/** + RegExp widget for `word boundary' + @internal +*/ +class WordBoundaryWidget : public ZeroWidget +{ +public: + WordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return WORDBOUNDARY; } +}; + + + + +/** + RegExp widget for `end of word' + @internal +*/ +class NonWordBoundaryWidget : public ZeroWidget +{ +public: + NonWordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return NONWORDBOUNDARY; } +}; + +#endif // zerowidget + |