m_table(table),
m_list(list),
m_cache(cache),
- m_includeExpr(),
- m_excludeExpr(),
+ m_includeExpr(NULL),
+ m_excludeExpr(NULL),
+ m_blockStartExpr(NULL),
+ m_blockEndExpr(NULL),
+ m_singleBlock(false),
m_caseSensitive(false),
m_fromHit(0),
m_toHit(0),
m_linesAbove(0),
m_linesBelow(0),
- m_lastHitPosition(lastHitPosition)
+ m_lastHitPosition(lastHitPosition),
+ m_prefixMode(pmNone)
{
}
const QString &excludePattern,
int fromHit, int pageSize,
int linesAbove, int linesBelow,
- bool caseSensitive)
+ bool caseSensitive, PrefixMode prefixMode,
+ const QString& blockStart, const QString& blockEnd,
+ bool singleBlock)
{
int ixFile = -1;
int hitNo = 0;
m_toHit = fromHit + pageSize - 1;
m_linesAbove = linesAbove;
m_linesBelow = linesBelow;
+ m_prefixMode = prefixMode;
+ m_singleBlock = singleBlock;
+
delete m_includeExpr;
delete m_excludeExpr;
+ delete m_blockStartExpr;
+ delete m_blockEndExpr;
QRegularExpression::PatternOption option = caseSensitive
? QRegularExpression::NoPatternOption
: QRegularExpression::CaseInsensitiveOption;
m_includeExpr = includePattern.isEmpty() ? NULL : new QRegularExpression(includePattern, option);
m_excludeExpr = excludePattern.isEmpty() ? NULL : new QRegularExpression(excludePattern, option);
-
+ m_blockStartExpr = includePattern.isEmpty() ? NULL : new QRegularExpression(blockStart, option);
+ m_blockEndExpr = excludePattern.isEmpty() ? NULL : new QRegularExpression(blockEnd, option);
+ QString full;
+ QString node;
+ int hitFileNo = -1;
while (ixFile < fileCount - 1 && hitNo < m_toHit){
++ixFile;
- QString full = m_table.item(ixFile, colPath)->text();
+ full = m_table.item(ixFile, colPath)->text();
full += OS_SEPARATOR_STR;
- full += m_table.item(ixFile, colNode)->text();
+ node = m_table.item(ixFile, colNode)->text();
+ full += node;
- hitNo = filterOneFile(full, hitNo);
+ hitNo = filterOneFile(full, node, hitNo, hitFileNo);
}
if (hitNo <= fromHit)
m_lastHitPosition.m_hitCount = 0;
* Filters the lines of one file.
*
* @param filename filename with path
+ * @param node filename without path
* @param lastHit the last found hit in the previous files
- * @return the number of hits including the hits in the file
+ * @param hitFileNo IN/OUT: The files with hits are numbered. This is
+ * the current number
+ * @return the number of hits including the hits in the file
*/
-int FileFilter::filterOneFile(const QString& filename, int lastHit)
+int FileFilter::filterOneFile(const QString& filename, const QString& node,
+ int lastHit, int& hitFileNo)
{
m_cache.addOrUpdate(filename);
const QStringList& lines = m_cache.lines(filename);
int lineNo = -1;
int lastLine = -1;
int lastIx = lines.size() - 1;
- QString prefixHit = filename + "-";
+ QString prefixHit;
+ switch(m_prefixMode){
+ case pmFull:
+ prefixHit = filename + "-";
+ break;
+ case pmNode:
+ prefixHit = node + '-';
+ break;
+ case pmNone:
+ case pmPlaceholder:
+ default:
+ break;
+ }
QString prefixOther = prefixHit;
if (m_linesAbove + m_linesBelow > 0){
prefixHit = ">" + prefixHit;
lastHit = m_lastHitPosition.m_hitNo;
lineNo = m_lastHitPosition.m_line;
}
+ int firstHitFile = true;
while(lastHit < m_toHit && lineNo < lastIx){
QString line = lines[++lineNo];
if (m_includeExpr != NULL && ! m_includeExpr->match(line).hasMatch())
if (m_lastHitPosition.m_hitNo > m_lastHitPosition.m_maxHitNo)
m_lastHitPosition.m_maxHitNo = m_lastHitPosition.m_hitNo;
if (lastHit >= m_fromHit){
+ if (firstHitFile && m_prefixMode == pmPlaceholder){
+ firstHitFile = false;
+ prefixHit = ReQStringUtils::numberToName(++hitFileNo) + '-';
+ }
for (int ix = max(lastLine + 1, max(0, lineNo - m_linesAbove));
ix <= min(lineNo + m_linesBelow, lastIx);
ix++){
public:
void filter(const QString& includePattern, const QString& excludePattern,
int fromHit, int toHit, int linesAbove, int linesBelow,
- bool caseSensitive);
+ bool caseSensitive, PrefixMode prefixMode,
+ const QString& blockStart, const QString& blockEnd,
+ bool singleBlock);
+
private:
- int filterOneFile(const QString &filename, int lastHit);
+ int filterOneFile(const QString &filename, const QString& node, int lastHit,
+ int& hitFileNo);
private:
QTableWidget& m_table;
QListWidget& m_list;
FileCache& m_cache;
QRegularExpression* m_includeExpr;
QRegularExpression* m_excludeExpr;
+ QRegularExpression* m_blockStartExpr;
+ QRegularExpression* m_blockEndExpr;
+ bool m_singleBlock;
bool m_caseSensitive;
int m_fromHit;
int m_toHit;
int m_linesAbove;
int m_linesBelow;
HitPosition& m_lastHitPosition;
+ PrefixMode m_prefixMode;
};
#endif // FILEFILTER_H
#include "research.hpp"
#include "mainwindow.hpp"
char** g_argv;
+void usage(const QString& error){
+ printf("%s\n", (QObject::tr("Usage: %1").arg(" research [<opts>] [<home_directory>]")).toLocal8Bit().data());
+ printf("<opt>:\n");
+ printf(" -d <base_directory> %s\n", QObject::tr("Sets the base directory").toLocal8Bit().data());
+ printf(" -f <file_pattern> %s\n", QObject::tr("Sets the file patterns").toLocal8Bit().data());
+ printf("%s\n", QObject::tr("Examples:").toLocal8Bit().data());
+ printf("research -d /home -f \"*.cpp;*.hpp;-*test*\"\n");
+ printf("research -d d:\\dev\\sources -f \"*.cpp;*.hpp;-*test*\"\n");
+ printf("%s\n", error.toLocal8Bit().data());
+ exit(1);
+}
+
int main(int argc, char* argv[]) {
g_argv = argv;
+ const char* baseDirectory = NULL;
+ const char* filePatterns = NULL;
+
+ while (argc > 1 && argv[1][0] == '-'){
+ switch(argv[1][1]){
+ case 'd':
+ if (argc < 3)
+ usage(QObject::tr("missing base directory"));
+ baseDirectory = argv[2];
+ --argc;
+ ++argv;
+ break;
+ case 'f':
+ if (argc < 3)
+ usage(QObject::tr("missing base directory"));
+ filePatterns = argv[2];
+ --argc;
+ ++argv;
+ break;
+ default:
+ usage(QObject::tr("unknown option: %1").arg(argv[1]));
+ break;
+ }
+ --argc;
+ ++argv;
+ }
QString homeDir = argc > 1 ? argv[1] : "";
QApplication a(argc, argv);
- MainWindow w(a, homeDir);
+ MainWindow w(a, homeDir,
+ baseDirectory == NULL ? QString("") : QString::fromLocal8Bit(baseDirectory),
+ filePatterns == NULL ? QString("") : QString::fromLocal8Bit(filePatterns));
w.show();
return a.exec();
}
static const int s_defaultPageSize = 10;
MainWindow::MainWindow(QApplication& application, const QString& homeDir,
- QWidget *parent) :
+ const QString& baseDirectory,
+ const QString& filePatterns,
+ QWidget *parent) :
ReGuiApplication(application, "rsearch", homeDir, 2, 10100100, "de", parent),
ReGuiValidator(),
ui(new Ui::MainWindow),
ReComboBox::setDefaultHistorySize(20);
m_timer->setSingleShot(true);
initializeGui();
+ if (! baseDirectory.isEmpty())
+ ui->comboBoxBaseDirectory->setCurrentText(baseDirectory);
+ if (! filePatterns.isEmpty())
+ ui->comboBoxFilePatterns->setCurrentText(filePatterns);
}
/**
ui->tableWidget->setColumnWidth(colDate, 175);
switchFilter(true);
if (m_test){
- //ui->comboBoxBaseDirectory->setCurrentText("/home/mhm");
- //ui->comboBoxFilePatterns->setCurrentText("pflege.odt");
- onAdd();
}
}
ui->pushButtonFilter->setEnabled(false);
filter.filter(ui->comboBoxIncludingPattern->currentText(),
ui->comboBoxExcludingPattern->currentText(),
- from, pageSize, above, below, false);
+ from, pageSize, above, below, false,
+ (PrefixMode) ui->comboBoxPrefixMode->currentIndex(),
+ ui->comboBoxStartPattern->currentText(),
+ ui->comboBoxEndPattern->currentText(),
+ ui->checkBoxSingleBlock->isChecked());
switchFilter(false);
int found = pageSize;
if (m_lastHitPosition->m_hitCount >= 0
public:
explicit MainWindow(QApplication& application, const QString& homeDir,
- QWidget *parent = 0);
+ const QString& baseDirectory,
+ const QString& filePatterns,
+ QWidget *parent = 0);
~MainWindow();
public:
virtual bool say(ReLoggerLevel level, const QString& message);
<attribute name="title">
<string>Options</string>
</attribute>
- <widget class="QWidget" name="layoutWidget">
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <item>
+ <layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0,1,0,2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMaximumSize</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Lines above:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="ReComboBox" name="comboBoxLinesAbove">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>175</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="currentText">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_9">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Lines below:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="ReComboBox" name="comboBoxLinesBelow">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>175</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="currentText">
+ <string notr="true">0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <widget class="QLabel" name="label_18">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Prefix:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="5">
+ <widget class="QComboBox" name="comboBoxPrefixMode">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>175</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <item>
+ <property name="text">
+ <string>Filename with path</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Filename without path</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Placeholder</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>No filename</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabBlock">
+ <attribute name="title">
+ <string>Block</string>
+ </attribute>
+ <layout class="QFormLayout" name="formLayout_5">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>Start pattern:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="ReComboBox" name="comboBoxStartPattern">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_17">
+ <property name="text">
+ <string>End pattern:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="ReComboBox" name="comboBoxEndPattern">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabBlockOptions">
+ <attribute name="title">
+ <string>Block Options</string>
+ </attribute>
+ <widget class="QCheckBox" name="checkBoxSingleBlock">
<property name="geometry">
<rect>
- <x>11</x>
- <y>11</y>
- <width>321</width>
- <height>38</height>
+ <x>20</x>
+ <y>20</y>
+ <width>171</width>
+ <height>25</height>
</rect>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <item>
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>Lines above:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="ReComboBox" name="comboBoxLinesAbove">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="editable">
- <bool>true</bool>
- </property>
- <property name="currentText">
- <string>0</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Lines below:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="ReComboBox" name="comboBoxLinesBelow">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="editable">
- <bool>true</bool>
- </property>
- <property name="currentText">
- <string notr="true">0</string>
- </property>
- </widget>
- </item>
- </layout>
+ <property name="text">
+ <string>A single block only</string>
+ </property>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
- <widget class="QWidget" name="tabBlock">
- <attribute name="title">
- <string>Block</string>
- </attribute>
- </widget>
</widget>
</item>
</layout>
#define RESEARCH_HPP
#include "base/rebase.hpp"
#include "gui/regui.hpp"
-#include "filefinder.hpp"
-#include "filecache.hpp"
-#include "filefilter.hpp"
-
enum ColumnFiles {
colNode = 0,
colSize,
colPath
};
+enum PrefixMode {
+ pmFull,
+ pmNode,
+ pmPlaceholder,
+ pmNone,
+};
+
+#include "filefinder.hpp"
+#include "filecache.hpp"
+#include "filefilter.hpp"
#endif // RESEARCH_HPP
}
}
+/**
+ * Converts a number into a name containing only characters 'A' - 'Z' and '_'.
+ *
+ * Negative numbers are marked with '_' at the end.
+ *
+ * @param number the number to convert
+ * @return the name which is unique to the number
+ */
+QString ReQStringUtils::numberToName(int number){
+ QString rc;
+ if (number < 0){
+ number = -number;
+ rc = '_';
+ }
+ do {
+ QChar cc('A' + number % 26);
+ number /= 26;
+ rc.insert(0, cc);
+ } while(number > 0);
+ return rc;
+}
+
/**
* Returns a readable string for a duration given by milliseconds.
*
uint* pValue = NULL);
static QString longestPrefix(const QStringList& list);
static bool match(const QString& heap, const QStringList& needles);
+ static QString numberToName(int number);
/**
* Returns the path with native path separators.
*
static char* utf8(const ReString& source, char buffer[], size_t bufferSize);
public:
static const QStringList m_emptyList;
- static const QString m_empty;
+ static const QString m_empty;
};
/**