diff --git a/docs/RELEASES b/docs/RELEASES
index dcec7df..333e2f2 100644
--- a/docs/RELEASES
+++ b/docs/RELEASES
@@ -1,3 +1,12 @@
+0.9.1 - Fixed the bug I totally missed when implementing hyperlink support
+ yesterday. They should now work properly.
+
+ Parser improvements: IMP should now be able to recognize multiple
+ sentences within an intel report and handle more complex reports
+ such as "20+ red KBP. XHQ clr! JEIV pocket status?".
+
+ Fixed a memory leak introduced in 0.9.0.
+
0.9.0 - Automatic update checking! Versions beyond 0.9.0 should alert you
when a new release has been uploaded/committed.
@@ -282,5 +291,6 @@
Coming soon:
- fix display of messages with backslashes.
+- fix bug where map starts updating only every 5 seconds.
- additional sound/volume options for alerts, dependant on jump distance.
- better pilot cache/cleanup.
diff --git a/src/chatitemdelegate.cpp b/src/chatitemdelegate.cpp
index cdd9ebf..9dccb51 100644
--- a/src/chatitemdelegate.cpp
+++ b/src/chatitemdelegate.cpp
@@ -65,7 +65,7 @@ void ChatItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
doc->documentLayout()->draw(painter, ctx);
painter->restore();
- doc->deleteLater();
+ delete doc;
}
}
@@ -114,6 +114,7 @@ QSize ChatItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QMode
doc->size().height() + padding.height() :
m_avatarSize.height() + padding.height());
+ delete doc;
return textSize;
}
@@ -126,7 +127,6 @@ QString ChatItemDelegate::anchorAt(const QStyleOptionViewItem& option,
QTextDocument* doc = document(options);
QAbstractTextDocumentLayout* textLayout = doc->documentLayout();
- doc->deleteLater();
Q_ASSERT(textLayout != 0);
@@ -135,5 +135,7 @@ QString ChatItemDelegate::anchorAt(const QStyleOptionViewItem& option,
QPoint p = point;
p.setX(p.x() - iconWidth - padding.width());
- return textLayout->anchorAt(p);
+ QString anchor = textLayout->anchorAt(p);
+ delete doc;
+ return anchor;
}
diff --git a/src/imp.pro b/src/imp.pro
index c83c9e1..315d08b 100644
--- a/src/imp.pro
+++ b/src/imp.pro
@@ -12,7 +12,7 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = imp
TEMPLATE = app
-VERSION = 0.9.0
+VERSION = 0.9.1
QMAKE_TARGET_COMPANY = EternalDusk
QMAKE_TARGET_DESCRIPTION = Eve Online Intelligence Management Program
QMAKE_TARGET_COPYRIGHT = (c) Copyright 2016-2017 Jesse Litton
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 79913d6..26b6179 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1245,7 +1245,7 @@ void MainWindow::fileChanged(const QString &absoluteFilePath)
}
}
- if(toBeAddedToList)
+ if(toBeAddedToList && message.skipOutput != true)
{
addMessage(message);
}
diff --git a/src/map.cpp b/src/map.cpp
index 5674e62..8a9c5f2 100755
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -29,7 +29,7 @@
Map::Map(QObject *parent) : QObject(parent)
{
m_timer = new QTimer(this);
- setRefresh(5000);
+ setRefresh(1000);
connect(m_timer, SIGNAL(timeout()), this, SLOT(updateActiveSystems()));
}
diff --git a/src/meta.h b/src/meta.h
index b40f76c..16299ba 100644
--- a/src/meta.h
+++ b/src/meta.h
@@ -27,8 +27,8 @@ static const struct Version
{
Version(){}
- QString release = "0.9.0"; //VERSION;
- QString name = "Round and Round Lycaan";
+ QString release = "0.9.1"; //VERSION;
+ QString name = "Lycaan Trophy";
QString styleHeader1 = "";
QString styleFooter1 = "";
diff --git a/src/parser.cpp b/src/parser.cpp
index 1a7f82d..5c98a89 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -26,7 +26,6 @@
#include
#include
#include
-#include
#include
#include
@@ -35,6 +34,8 @@ using namespace std;
Parser::Parser(uint generation, QObject *parent) : QObject(parent)
{
this->generation = generation;
+
+ listener.setMinimal(true);
ignoreChars = "[\\\\_=!@#$%^&\\*,\\.\\[\\]\\(\\)\\{\\}\\?]"; // "\\_=!@#$%^&*,./[](){}?"
@@ -135,23 +136,28 @@ QList Parser::fileChanged(const QString& path, int maxEntries, bool
for (int i=startLine; i newMessages = parseLine(lines[i].trimmed().remove(0xfeff));
- newMessage.parserGeneration = generation;
- newMessage.logInfo = &fileMap[path];
- if(newMessage.systems.length() > 0)
+ // Okay, these aren't really separate user-messages... they are
+ // messages to be processed by main window... clean up later.
+ foreach(MessageInfo newMessage, newMessages)
{
- newMessage.logInfo->systemLastMentioned = newMessage.systems[0];
- }
-
- if (!newMessage.indecipherable)
- {
- messageInfoList.append(newMessage);
- }
- else
- {
- qDebug() << "Parser::fileChanged() - Indecipherable message: " <<
- fileMap[path].channel << "> " << lines[i] << endl;
+ newMessage.parserGeneration = generation;
+ newMessage.logInfo = &fileMap[path];
+ if(newMessage.systems.length() > 0)
+ {
+ newMessage.logInfo->systemLastMentioned = newMessage.systems[0];
+ }
+
+ if (!newMessage.indecipherable)
+ {
+ messageInfoList.append(newMessage);
+ }
+ else
+ {
+ qDebug() << "Parser::fileChanged() - Indecipherable message: " <<
+ fileMap[path].channel << "> " << lines[i] << endl;
+ }
}
}
fileMap[path].position = input.pos();
@@ -159,64 +165,167 @@ QList Parser::fileChanged(const QString& path, int maxEntries, bool
return messageInfoList;
}
-MessageInfo Parser::parseLine(const QString& line)
+QList Parser::parseLine(const QString& line)
{
- MessageInfo messageInfo;
- messageInfo.originalLine = line;
+ QList messages;
+
+ QDateTime dateTime;
+ QString sender, text;
- // Get timestamp
- QRegExp listener("^\\[ (.{19}) \\] ([^>]+) > ([^\\.\\?!]*)(.*)$");
- listener.setMinimal(true);
+ // Does message look valid?
if (listener.indexIn(line.trimmed()) != -1)
{
- messageInfo.indecipherable = false;
+ dateTime = QDateTime::fromString(listener.cap(1), "yyyy.MM.dd HH:mm:ss");
+ dateTime.setTimeSpec(Qt::UTC);
+ sender = listener.cap(2);
+ text = listener.cap(3);
+ }
+ else
+ {
+ // Can't make heads or tails of this, return upstream.
+ MessageInfo messageInfo;
+ messageInfo.originalLine = line;
+ messageInfo.indecipherable = true;
+ messages.append(messageInfo);
+ return messages;
+ }
+
- QString cap1 = listener.cap(1);
- messageInfo.dateTime = QDateTime::fromString(listener.cap(1), "yyyy.MM.dd HH:mm:ss");
+ // Is this a system message?
+ if (sender == "EVE System")
+ {
+ MessageInfo messageInfo;
+ messageInfo.originalLine = line;
+ messageInfo.dateTime = dateTime;
messageInfo.dateTime.setTimeSpec(Qt::UTC);
- messageInfo.sender = listener.cap(2);
+ messageInfo.sender = sender;
+ messageInfo.text = text;
- messageInfo.text = listener.cap(3);
+ // Test to see if this is a system change message:
+ // EVE System > Channel changed to Local : JEIV-E
- if (messageInfo.sender == "EVE System")
+ QRegExp sysMsgRegExp("^Channel changed to .* : (.*)$");
+ sysMsgRegExp.setMinimal(true);
+ if (sysMsgRegExp.indexIn(text.trimmed()) != -1)
{
- //qDebug() << "Parser::parseLine(" << line << ")";
+ //qDebug() << " is a system change message.";
+ messageInfo.systems.append(sysMsgRegExp.cap(1));
+ messageInfo.flags.append(MessageFlag::SYSTEM_CHANGE);
+ messages.append(messageInfo);
+ return messages;
+ }
- // Test to see if this is a system change message:
- // EVE System > Channel changed to Local : JEIV-E
+ // Test to see if this is a MOTD message:
- QRegExp sysMsgRegExp("^Channel changed to .* : (.*)$");
- sysMsgRegExp.setMinimal(true);
- if (sysMsgRegExp.indexIn(messageInfo.text.trimmed()) != -1)
- {
- //qDebug() << " is a system change message.";
- messageInfo.systems.append(sysMsgRegExp.cap(1));
- messageInfo.flags.append(MessageFlag::SYSTEM_CHANGE);
- return messageInfo;
- }
+ QRegExp motdRegExp("^Channel MOTD: (.*)$");
+ if (motdRegExp.indexIn(messageInfo.text.trimmed()) != -1)
+ {
+ messageInfo.flags.append(MOTD);
+ messages.append(messageInfo);
+ return messages;
+ }
- // Test to see if this is a MOTD message:
+ // Test to see if this is an ESS message:
+ QRegExp essRegExp("(.*) is now in proximity of the Encounter Surveillance System$");
+ if (essRegExp.indexIn(messageInfo.text.trimmed()) != -1)
+ {
+ messageInfo.flags.append(ESS);
+ messageInfo.related.append(essRegExp.cap(1));
+ messages.append(messageInfo);
+ return messages;
+ }
+ }
- QRegExp motdRegExp("^Channel MOTD: (.*)$");
- if (motdRegExp.indexIn(messageInfo.text.trimmed()) != -1)
- {
- messageInfo.flags.append(MOTD);
- return messageInfo;
- }
- // Test to see if this is an ESS message:
- QRegExp essRegExp("(.*) is now in proximity of the Encounter Surveillance System$");
- if (essRegExp.indexIn(messageInfo.text.trimmed()) != -1)
- {
- messageInfo.flags.append(ESS);
- messageInfo.related.append(essRegExp.cap(1));
- return messageInfo;
- }
+ // Valid, non-system message. Deconstruct it into sentences and words.
+ QRegExp puncPreExp("^" + ignoreChars + "+");
+ QRegExp puncPostExp(ignoreChars + "+$");
+
+ int currentPos = 0,
+ nextSpace = 0;
+ QList* impSentence = new QList;
+ QList> impSentences;
+ // Build sentences and their word info.
+ while(currentPos <= text.length())
+ {
+ ImpWord impWord;
+
+ nextSpace = text.indexOf(' ', currentPos+1);
+ if(nextSpace == -1)
+ nextSpace = text.length();
+
+ if(text[currentPos] == ' ')
+ {
+ currentPos++;
+ continue;
+ }
+
+ impWord.raw = text.mid(currentPos, nextSpace-currentPos);
+ qDebug() << "Parser::identifyObjects - raw =" << impWord.raw;
+
+ if (puncPostExp.indexIn(impWord.raw) != -1)
+ impWord.postfix = puncPostExp.cap();
+ else
+ impWord.postfix = "";
+ impWord.postfixStart = currentPos + impWord.raw.length() - impWord.postfix.length();
+
+ // Only build prefix punctuation, if entire string wasn't punctuation.
+ if(impWord.postfix != impWord.raw)
+ {
+ if (puncPreExp.indexIn(impWord.raw) != -1)
+ impWord.prefix = puncPreExp.cap();
+ else
+ impWord.prefix = "";
+ }
+ impWord.prefixStart = currentPos;
+
+ qDebug() << "Parser::identifyObjects - prefix =" << impWord.prefix <<
+ ", prefixStart =" << impWord.prefixStart <<
+ ", postfix =" << impWord.postfix <<
+ ", postfixStart =" << impWord.postfixStart;
+
+ impWord.actual = impWord.raw.mid(impWord.prefix.length(),
+ impWord.raw.length()-impWord.postfix.length());
+
+ qDebug() << "Parser::identifyObjects - actual =" << impWord.actual;
+
+ currentPos = nextSpace + 1;
+ impSentence->append(impWord);
+
+ if(nextSpace >= text.length())
+ impSentences.append(*impSentence);
+ else if(impWord.postfix.endsWith('.') ||
+ impWord.postfix.endsWith('!') ||
+ impWord.postfix.endsWith('?'))
+ {
+ impSentences.append(*impSentence);
+ delete impSentence;
+ impSentence = new QList;
}
+ }
+ delete impSentence;
+
+ // Now process each sentence in the message and return a message for each.
+
+ QString markedUpText = "";
+ foreach(QList s, impSentences)
+ {
+ qDebug() << "impSentence:";
+ foreach (ImpWord iw, s) {
+ qDebug() << '\t' << iw.prefix << iw.actual << iw.postfix;
+ }
+
+ MessageInfo messageInfo;
+ messageInfo.originalLine = line;
+ messageInfo.dateTime = dateTime;
+ messageInfo.dateTime.setTimeSpec(Qt::UTC);
+ messageInfo.sender = sender;
+ messageInfo.text = text;
+ messageInfo.skipOutput = true;
// Bring in some bison later and dump this simple placeholder
- identifyObjects(messageInfo);
+ markedUpText += identifyObjects(messageInfo, s);
QString endingPunctuation = listener.cap(4);
//qDebug() << "endingPunctuation = " << endingPunctuation;
@@ -231,74 +340,73 @@ MessageInfo Parser::parseLine(const QString& line)
{
messageInfo.flags.append(MessageFlag::WARNING);
}
- }
- else
- {
- messageInfo.indecipherable = true;
+
+ messages.append(messageInfo);
}
- return messageInfo;
+ messages[messages.count()-1].markedUpText = markedUpText;
+ messages[messages.count()-1].skipOutput = false;
+ return messages;
}
-void Parser::identifyObjects(MessageInfo& messageInfo)
+QString Parser::identifyObjects(MessageInfo& messageInfo, QList &sentence)
{
+ QString markedUpText = "";
QStringList theseSystems;
QStringList theseShips;
QStringList theseGates;
- // Turn any punctuation into whitespace and remove all redundant whitespace.
- // Makes things like "name in XX-XXX...svipul" not get misparsed.
- QString simChat = messageInfo.text;
- simChat = simChat.replace(QRegExp(ignoreChars), " ");
- simChat = simChat.simplified();
- QStringList words = simChat.split(" ");
+ // New parsing
+ qDebug() << "Parser::identifyObjects - Parsing sentence in: " << messageInfo.text;
- messageInfo.markedUpText = "";
-
- QString previousWord = "";
- for (int i = 0; i < words.length(); i++)
+ for(int i=0; i";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
else if (locationWords.contains(lowerWord))
{
messageInfo.flags.append(MessageFlag::LOCATION);
-
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
else if (clearWords.contains(lowerWord))
{
- if(previousWord != "gate")
+ if(i > 0 && sentence[i].actual.toLower() != "gate")
{
// We don't want to clear a system if someone says a gate is clear.
// "> KBP Dital gate clr!"
messageInfo.flags.append(MessageFlag::CLEAR);
-
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
}
else if(ships.contains(lowerWord))
{
- theseShips.append(words[i]);
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ theseShips.append(sentence[i].actual);
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
else if(lowerWord == "pocket")
{
@@ -306,69 +414,78 @@ void Parser::identifyObjects(MessageInfo& messageInfo)
}
else if(lowerWord.contains(QRegExp("[^ ]{3,5}://.+")))
{
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += "";
+ markedUpText += sentence[i].raw;
+ markedUpText += "";
messageInfo.flags.append(MessageFlag::LINK);
}
else
{
- QString systemName = regionMap->getSystemByAbbreviation(words[i].toUpper());
+ QString systemName = regionMap->getSystemByAbbreviation(sentence[i].actual.toUpper());
if(systemName.length() > 0)
{
- if(i < (words.length()-1) && words[i+1].toLower() == "gate")
+ if(i < (sentence.length()-1) && sentence[i+1].actual.toLower() == "gate")
{
- if(i < (words.length()-2) && words[i+2].toLower() == "to")
+ if(i < (sentence.length()-2) && sentence[i+2].actual.toLower() == "to")
{
// "x-x gate to..."
theseSystems.append(systemName);
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
else {
// "...at x-x gate"
theseGates.append(systemName);
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
}
- else if(i > 0 && left.contains(words[i-1].toLower()) )
+ else if(i > 0 && left.contains(sentence[i-1].actual.toLower()) )
{
// Check to see if it is "left *system*", "from *system*", etc.
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
else
{
// System mentioned, not adjacent to word 'gate' or one of
// the words indicating they left a system.
theseSystems.append(systemName);
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += "";
+ markedUpText += sentence[i].actual;
+ markedUpText += "";
+ markedUpText += sentence[i].postfix;
}
}
else if(lowerWord.length() >= 2)
{
- messageInfo.possiblePilots.append(words[i]);
- messageInfo.markedUpText += "";
- messageInfo.markedUpText += words[i];
- messageInfo.markedUpText += "";
+ messageInfo.possiblePilots.append(sentence[i].actual);
+ markedUpText += "";
+ markedUpText += sentence[i].prefix;
+ markedUpText += sentence[i].actual;
+ markedUpText += sentence[i].postfix;
}
}
- previousWord = lowerWord;
-
- if(i < words.length())
- messageInfo.markedUpText += " ";
+ if(i < sentence.length())
+ markedUpText += " ";
}
messageInfo.systems = theseSystems;
messageInfo.ships = theseShips;
messageInfo.gates = theseGates;
+
+ return markedUpText;
}
diff --git a/src/parser.h b/src/parser.h
index 3adf09f..bdfd995 100755
--- a/src/parser.h
+++ b/src/parser.h
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -51,6 +52,8 @@ struct LogInfo
struct MessageInfo
{
uint parserGeneration = 0;
+ bool skipOutput = false;
+
QString originalLine;
bool indecipherable = false;
@@ -70,6 +73,16 @@ struct MessageInfo
QList flags;
};
+struct ImpWord
+{
+ QString raw;
+ QString prefix;
+ int prefixStart;
+ QString actual;
+ QString postfix;
+ int postfixStart;
+};
+
class Parser : public QObject
{
Q_OBJECT
@@ -90,6 +103,9 @@ public slots:
private:
uint generation = 0;
+ //QRegExp listener = QRegExp("^\\[ (.{19}) \\] ([^>]+) > ([^\\.\\?!]*)(.*)$");
+ QRegExp listener = QRegExp("^\\[ (.{19}) \\] ([^>]+) > (.*)$");
+
QString lastListener;
QString lastLocalSystem;
@@ -106,9 +122,9 @@ public slots:
Map* regionMap;
void loadSet(QSet& set, QString& string);
- void identifyObjects(MessageInfo& messageInfo);
+ QString identifyObjects(MessageInfo& messageInfo, QList& sentence);
QString systemAbbreviation(const QString& word);
- MessageInfo parseLine(const QString& line);
+ QList parseLine(const QString& line);
};
#endif // PARSER_H
diff --git a/src/svgmapview.cpp b/src/svgmapview.cpp
index 673e58e..86907c6 100755
--- a/src/svgmapview.cpp
+++ b/src/svgmapview.cpp
@@ -72,6 +72,7 @@ SvgMapView::SvgMapView(QWidget *parent) : QGraphicsView(parent)
SvgMapView::~SvgMapView()
{
+ qDeleteAll(pilotShapes.begin(), pilotShapes.end());
findShape->deleteLater();
}