00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ctagsdlg.h"
00013
00014 #include <qcheckbox.h>
00015 #include <qfile.h>
00016 #include <qhbox.h>
00017 #include <qheader.h>
00018 #include <qlabel.h>
00019 #include <qlayout.h>
00020 #include <qlineedit.h>
00021 #include <qlistview.h>
00022 #include <qpushbutton.h>
00023 #include <qtextstream.h>
00024 #include <qregexp.h>
00025 #include <kbuttonbox.h>
00026 #include <kdebug.h>
00027 #include <kdialog.h>
00028 #include <klistbox.h>
00029 #include <klocale.h>
00030 #include <kmessagebox.h>
00031 #include <kstdguiitem.h>
00032 #include <kdeversion.h>
00033
00034 #include "kdevplugin.h"
00035 #include "kdevcore.h"
00036 #include "kdevpartcontroller.h"
00037 #include "kdevproject.h"
00038 #include "ctagskinds.h"
00039
00040
00041 class CTagsResultItem : public QListBoxText
00042 {
00043 public:
00044 CTagsResultItem(QListBox *parent, const QString &fileName, const QString pattern,
00045 const QString &kindString)
00046 : QListBoxText(parent, QString("%1:%2 (%3)").arg(fileName).arg(pattern).arg(kindString)),
00047 m_fileName(fileName), m_pattern(pattern), m_kindString(kindString)
00048 {}
00049
00050 QString fileName() const
00051 { return m_fileName; }
00052 QString pattern() const
00053 { return m_pattern; }
00054
00055 private:
00056 QString m_fileName;
00057 QString m_pattern;
00058 QString m_kindString;
00059 };
00060
00061
00062 CTagsDialog::CTagsDialog(CTagsPart *part)
00063 : QDialog(0, "ctags dialog", false)
00064 {
00065 setCaption(i18n("Search in Tags"));
00066 QFontMetrics fm(fontMetrics());
00067
00068 QLabel *tagLabel = new QLabel(i18n("&Tag:"), this);
00069
00070 tagEdit = new QLineEdit(this);
00071 tagEdit->setFocus();
00072 tagLabel->setBuddy(tagEdit);
00073 tagEdit->setMinimumWidth(fm.width('X')*30);
00074
00075 regexpBox = new QCheckBox(i18n("&Regular expression match"), this);
00076 regexpBox->setChecked(true);
00077
00078 QLabel *kindsLabel = new QLabel(i18n("&Kinds:"), this);
00079
00080 kindsListView = new QListView(this);
00081 kindsLabel->setBuddy(kindsListView);
00082 kindsListView->setResizeMode(QListView::LastColumn);
00083 kindsListView->addColumn(QString::null);
00084 kindsListView->header()->hide();
00085 kindsListView->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
00086
00087 KButtonBox *actionBox = new KButtonBox(this, Qt::Vertical);
00088 actionBox->addStretch();
00089 QPushButton *regenerateButton = actionBox->addButton(i18n("&Regenerate"));
00090 regenerateButton->setDefault(true);
00091 #if KDE_IS_VERSION( 3, 2, 90 )
00092 QPushButton *cancelButton = actionBox->addButton(KStdGuiItem::close());
00093 #else
00094 QPushButton *cancelButton = actionBox->addButton(i18n("Close"));
00095 #endif
00096 actionBox->addStretch();
00097 actionBox->layout();
00098
00099 resultsListBox = new KListBox(this);
00100 resultsListBox->setMinimumHeight(fm.lineSpacing()*10);
00101 resultsListBox->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding));
00102
00103 QGridLayout *layout = new QGridLayout(this, 5, 2, KDialog::marginHint(), KDialog::spacingHint());
00104 layout->addRowSpacing(3, 10);
00105 layout->addWidget(tagLabel, 0, 0);
00106 layout->addWidget(tagEdit, 0, 1);
00107 layout->addWidget(regexpBox, 1, 1);
00108 layout->addWidget(kindsLabel, 2, 0);
00109 layout->addWidget(kindsListView, 2, 1);
00110 layout->addMultiCellWidget(actionBox, 0, 2, 2, 2);
00111 layout->addMultiCellWidget(resultsListBox, 4, 4, 0, 2);
00112
00113 connect( tagEdit, SIGNAL(textChanged(const QString&)),
00114 this, SLOT(slotSearch()) );
00115 connect( kindsListView, SIGNAL(clicked(QListViewItem*)),
00116 this, SLOT(slotSearch()) );
00117 connect( kindsListView, SIGNAL(returnPressed(QListViewItem*)),
00118 this, SLOT(slotSearch()) );
00119 connect( regexpBox, SIGNAL(toggled(bool)),
00120 this, SLOT(slotSearch()) );
00121 connect( regenerateButton, SIGNAL(clicked()),
00122 this, SLOT(slotRegenerate()) );
00123 connect( cancelButton, SIGNAL(clicked()),
00124 this, SLOT(reject()) );
00125 connect( resultsListBox, SIGNAL(clicked(QListBoxItem*)),
00126 this, SLOT(slotResultClicked(QListBoxItem*)) );
00127 connect( resultsListBox, SIGNAL(returnPressed(QListBoxItem*)),
00128 this, SLOT(slotResultClicked(QListBoxItem*)) );
00129
00130 m_part = part;
00131 updateInfo();
00132 }
00133
00134
00135 CTagsDialog::~CTagsDialog()
00136 {}
00137
00138
00139 void CTagsDialog::updateInfo()
00140 {
00141 m_tags = m_part->tags();
00142 m_kindStrings = m_part->kindStrings();
00143
00144 kindsListView->clear();
00145
00146 QStringList::ConstIterator it;
00147 for (it = m_kindStrings.begin(); it != m_kindStrings.end(); ++it) {
00148 QCheckListItem *item = new QCheckListItem(kindsListView, (*it), QCheckListItem::CheckBox);
00149 item->setOn(true);
00150 }
00151 }
00152
00153
00154 void CTagsDialog::slotSearch()
00155 {
00156 kdDebug(9022) << "search tag" << endl;
00157 if (m_tags.isEmpty())
00158 return;
00159
00160
00161 QStringList kindStringList;
00162 QCheckListItem *clitem = static_cast<QCheckListItem*>(kindsListView->firstChild());
00163 while (clitem) {
00164 if (clitem->isOn())
00165 kindStringList.append(clitem->text());
00166 clitem = static_cast<QCheckListItem*>(clitem->nextSibling());
00167 }
00168 resultsListBox->clear();
00169
00170 if (regexpBox->isChecked()) {
00171
00172 QRegExp re(tagEdit->text());
00173 CTagsMapConstIterator it;
00174 for (it = m_tags.begin(); it != m_tags.end(); ++it)
00175 if (re.exactMatch(it.key()))
00176 insertResult(it.data(), kindStringList);
00177 } else {
00178
00179 CTagsMapIterator result = m_tags.find(tagEdit->text());
00180 if (result != m_tags.end())
00181 insertResult(*result, kindStringList);
00182 }
00183 }
00184
00185
00186 void CTagsDialog::insertResult(const CTagsTagInfoList &result, const QStringList &kindStringList)
00187 {
00188
00189
00190 CTagsTagInfoListConstIterator it;
00191 for (it = result.begin(); it != result.end(); ++it) {
00192 QString extension;
00193 if ((*it).fileName.right(9) == "/Makefile")
00194 extension = "mak";
00195 else {
00196 int pos = (*it).fileName.findRev('.');
00197 if (pos > 0)
00198 extension = (*it).fileName.mid(pos+1);
00199 }
00200 if (extension.isNull())
00201 continue;
00202 QString kindString = CTagsKinds::findKind((*it).kind, extension);
00203 if (!kindStringList.contains(kindString))
00204 continue;
00205
00206 new CTagsResultItem(resultsListBox, (*it).fileName, (*it).pattern, kindString);
00207 }
00208 }
00209
00210
00211 void CTagsDialog::slotRegenerate()
00212 {
00213 if (!m_part->createTagsFile()) {
00214 KMessageBox::sorry(this, i18n("Could not create tags file"));
00215 return;
00216 }
00217
00218 m_part->loadTagsFile();
00219
00220 updateInfo();
00221 }
00222
00223
00224 void CTagsDialog::slotResultClicked(QListBoxItem *item)
00225 {
00226 if (!item)
00227 return;
00228
00229 CTagsResultItem *ritem = static_cast<CTagsResultItem*>(item);
00230 QString fileName = ritem->fileName();
00231 if (!fileName.startsWith("/"))
00232 fileName.prepend(m_part->project()->projectDirectory() + "/");
00233 QString pattern = ritem->pattern();
00234 bool ok;
00235 int lineNum = pattern.toInt(&ok);
00236 if (!ok) {
00237 KMessageBox::sorry(0, i18n("Currently, only tags with line numbers (option -n) are supported"));
00238 return;
00239 }
00240
00241 m_part->partController()->editDocument(KURL::fromPathOrURL( fileName ), lineNum-1);
00242 }
00243
00244 #include "ctagsdlg.moc"