summaryrefslogtreecommitdiffstats
path: root/qt-ui
diff options
context:
space:
mode:
Diffstat (limited to 'qt-ui')
-rw-r--r--qt-ui/completionmodels.cpp13
-rw-r--r--qt-ui/completionmodels.h7
-rw-r--r--qt-ui/groupedlineedit.cpp204
-rw-r--r--qt-ui/groupedlineedit.h66
-rw-r--r--qt-ui/maintab.cpp40
-rw-r--r--qt-ui/maintab.h4
-rw-r--r--qt-ui/maintab.ui121
-rw-r--r--qt-ui/tagwidget.cpp135
-rw-r--r--qt-ui/tagwidget.h26
9 files changed, 572 insertions, 44 deletions
diff --git a/qt-ui/completionmodels.cpp b/qt-ui/completionmodels.cpp
index 8bd4f5441..31733addb 100644
--- a/qt-ui/completionmodels.cpp
+++ b/qt-ui/completionmodels.cpp
@@ -12,6 +12,7 @@ CREATE_SINGLETON(BuddyCompletionModel);
CREATE_SINGLETON(DiveMasterCompletionModel);
CREATE_SINGLETON(LocationCompletionModel);
CREATE_SINGLETON(SuitCompletionModel);
+CREATE_SINGLETON(TagCompletionModel);
#undef CREATE_SINGLETON
@@ -35,3 +36,15 @@ CREATE_UPDATE_METHOD(DiveMasterCompletionModel, divemaster);
CREATE_UPDATE_METHOD(LocationCompletionModel, location);
CREATE_UPDATE_METHOD(SuitCompletionModel, suit);
+void TagCompletionModel::updateModel()
+{
+ if(g_tag_list == NULL)
+ return;
+ QStringList list;
+ struct tag_entry *current_tag_entry = g_tag_list->next;
+ while (current_tag_entry != NULL) {
+ list.append(QString(current_tag_entry->tag->name));
+ current_tag_entry = current_tag_entry->next;
+ }
+ setStringList(list);
+}
diff --git a/qt-ui/completionmodels.h b/qt-ui/completionmodels.h
index e4f1770e2..146186531 100644
--- a/qt-ui/completionmodels.h
+++ b/qt-ui/completionmodels.h
@@ -31,4 +31,11 @@ public:
void updateModel();
};
+class TagCompletionModel : public QStringListModel {
+ Q_OBJECT
+public:
+ static TagCompletionModel* instance();
+ void updateModel();
+};
+
#endif
diff --git a/qt-ui/groupedlineedit.cpp b/qt-ui/groupedlineedit.cpp
new file mode 100644
index 000000000..7502db5ce
--- /dev/null
+++ b/qt-ui/groupedlineedit.cpp
@@ -0,0 +1,204 @@
+/*
+ * This file is part of the Nepomuk widgets collection
+ * Copyright (c) 2013 Denis Steckelmacher <steckdenis@yahoo.fr>
+ *
+ * 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.1 as published by the Free Software Foundation,
+ * or any later version.
+ *
+ * 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 "groupedlineedit.h"
+
+#include <QtGui/QStyleOptionFrameV3>
+#include <QtGui/QFontMetrics>
+#include <QtGui/QApplication>
+#include <QtGui/QScrollBar>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextLayout>
+#include <QtGui/QTextLine>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+#include <QtGui/QBrush>
+#include <QtGui/QColor>
+#include <QtGui/QPalette>
+
+struct GroupedLineEdit::Private
+{
+ struct Block {
+ int start;
+ int end;
+ QString text;
+ };
+ QVector<Block> blocks;
+ QVector<QColor> colors;
+};
+
+GroupedLineEdit::GroupedLineEdit(QWidget* parent)
+: QPlainTextEdit(parent),
+ d(new Private)
+{
+ setWordWrapMode(QTextOption::NoWrap);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ document()->setMaximumBlockCount(1);
+}
+
+
+GroupedLineEdit::~GroupedLineEdit()
+{
+ delete d;
+}
+
+QString GroupedLineEdit::text() const
+{
+ // Remove the block crosses from the text
+ return toPlainText();
+}
+
+int GroupedLineEdit::cursorPosition() const
+{
+ return textCursor().positionInBlock();
+}
+
+void GroupedLineEdit::addBlock(int start, int end)
+{
+ Private::Block block;
+
+ block.start = start;
+ block.end = end;
+ block.text = text().mid(start, end-start+1).trimmed();
+ d->blocks.append(block);
+ viewport()->update();
+}
+
+void GroupedLineEdit::addColor(QColor color)
+{
+ d->colors.append(color);
+}
+
+void GroupedLineEdit::removeAllColors()
+{
+ d->colors.clear();
+}
+
+QStringList GroupedLineEdit::getBlockStringList()
+{
+ QStringList retList;
+ Private::Block block;
+ foreach(block, d->blocks)
+ retList.append(block.text);
+ return retList;
+}
+
+void GroupedLineEdit::setCursorPosition(int position)
+{
+ QTextCursor c = textCursor();
+
+ c.setPosition(position, QTextCursor::MoveAnchor);
+
+ setTextCursor(c);
+}
+
+void GroupedLineEdit::setText(const QString &text)
+{
+ setPlainText(text);
+}
+
+void GroupedLineEdit::clear()
+{
+ QPlainTextEdit::clear();
+ removeAllBlocks();
+}
+
+void GroupedLineEdit::selectAll()
+{
+ QTextCursor c = textCursor();
+
+ c.select(QTextCursor::LineUnderCursor);
+
+ setTextCursor(c);
+}
+
+void GroupedLineEdit::removeAllBlocks()
+{
+ d->blocks.clear();
+ viewport()->update();
+}
+
+QSize GroupedLineEdit::sizeHint() const
+{
+ QSize rs(
+ 40,
+ document()->findBlock(0).layout()->lineAt(0).height() +
+ document()->documentMargin() * 2 +
+ frameWidth() * 2
+ );
+
+ return rs;
+}
+
+QSize GroupedLineEdit::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
+void GroupedLineEdit::keyPressEvent(QKeyEvent *e)
+{
+ switch (e->key()) {
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ emit editingFinished();
+ return;
+ }
+
+ QPlainTextEdit::keyPressEvent(e);
+}
+
+void GroupedLineEdit::paintEvent(QPaintEvent *e)
+{
+
+ QTextLine line = document()->findBlock(0).layout()->lineAt(0);
+ QPainter painter(viewport());
+
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
+
+ painter.fillRect(0, 0, viewport()->width(), viewport()->height(), palette().base());
+
+ QVectorIterator<QColor> i(d->colors);
+ i.toFront();
+ foreach (const Private::Block &block, d->blocks) {
+ qreal start_x = line.cursorToX(block.start, QTextLine::Trailing);
+ qreal end_x = line.cursorToX(block.end + 1, QTextLine::Leading);
+ QPainterPath path;
+ QRectF rectangle(
+ start_x - 1.0 - double(horizontalScrollBar()->value()),
+ 1.0,
+ end_x - start_x + 2.0,
+ double(viewport()->height() - 2)
+ );
+ if (! i.hasNext())
+ i.toFront();
+ path.addRoundedRect(rectangle, 5.0, 5.0);
+ painter.setPen(i.peekNext());
+ painter.setBrush(i.next().lighter(180));
+ painter.drawPath(path);
+ }
+
+ QPlainTextEdit::paintEvent(e);
+}
diff --git a/qt-ui/groupedlineedit.h b/qt-ui/groupedlineedit.h
new file mode 100644
index 000000000..327932c9d
--- /dev/null
+++ b/qt-ui/groupedlineedit.h
@@ -0,0 +1,66 @@
+/* Original License:
+ *
+ * This file is part of the Nepomuk widgets collection
+ * Copyright (c) 2013 Denis Steckelmacher <steckdenis@yahoo.fr>
+ *
+ * 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.1 as published by the Free Software Foundation,
+ * or any later version.
+ *
+ * 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 __GROUPEDLINEEDIT_H__
+#define __GROUPEDLINEEDIT_H__
+
+#include <QtGui/QPlainTextEdit>
+#include <QStringList>
+
+class GroupedLineEdit : public QPlainTextEdit
+{
+ Q_OBJECT
+
+public:
+ explicit GroupedLineEdit(QWidget *parent = 0);
+ virtual ~GroupedLineEdit();
+
+ QString text() const;
+
+ int cursorPosition() const;
+ void setCursorPosition(int position);
+ void setText(const QString &text);
+ void clear();
+ void selectAll();
+
+ void removeAllBlocks();
+ void addBlock(int start, int end);
+ QStringList getBlockStringList();
+
+ void addColor(QColor color);
+ void removeAllColors();
+
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+signals:
+ void editingFinished();
+
+protected:
+ virtual void paintEvent(QPaintEvent *e);
+ virtual void keyPressEvent(QKeyEvent *e);
+
+private:
+ struct Private;
+ Private *d;
+};
+#endif
diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp
index ddcdc6c63..b7c0f15c7 100644
--- a/qt-ui/maintab.cpp
+++ b/qt-ui/maintab.cpp
@@ -58,6 +58,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
ui.airtemp->installEventFilter(this);
ui.watertemp->installEventFilter(this);
ui.dateTimeEdit->installEventFilter(this);
+ ui.tagWidget->installEventFilter(this);
QList<QObject *> statisticsTabWidgets = ui.statisticsTab->children();
Q_FOREACH(QObject* obj, statisticsTabWidgets) {
@@ -87,10 +88,12 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
completers.divemaster = new QCompleter(DiveMasterCompletionModel::instance(), ui.divemaster);
completers.location = new QCompleter(LocationCompletionModel::instance(), ui.location);
completers.suit = new QCompleter(SuitCompletionModel::instance(), ui.suit);
+ completers.tags = new QCompleter(TagCompletionModel::instance(), ui.tagWidget);
ui.buddy->setCompleter(completers.buddy);
ui.divemaster->setCompleter(completers.divemaster);
ui.location->setCompleter(completers.location);
ui.suit->setCompleter(completers.suit);
+ ui.tagWidget->setCompleter(completers.tags);
setMinimumHeight(0);
setMinimumWidth(0);
@@ -161,6 +164,9 @@ void MainTab::enableEdition(EditMode newEditMode)
notesBackup[mydive].airtemp = get_temperature_string(mydive->airtemp, true);
notesBackup[mydive].watertemp = get_temperature_string(mydive->watertemp, true);
notesBackup[mydive].datetime = QDateTime::fromTime_t(mydive->when - gettimezoneoffset()).toString(QString("M/d/yy h:mm"));
+ char buf[1024];
+ taglist_get_tagstring(mydive->tag_list, buf, 1024);
+ notesBackup[mydive].tags = QString(buf);
// maybe this is a place for memset?
for (int i = 0; i < MAX_CYLINDERS; i++) {
@@ -182,7 +188,9 @@ bool MainTab::eventFilter(QObject* object, QEvent* event)
enableEdition();
}
- if (isEnabled() && event->type() == QEvent::FocusIn && (object == ui.rating || object == ui.visibility)) {
+ if (isEnabled() && event->type() == QEvent::FocusIn && (object == ui.rating ||
+ object == ui.visibility ||
+ object == ui.tagWidget)) {
tabBar()->setTabIcon(currentIndex(), QIcon(":warning"));
enableEdition();
}
@@ -215,6 +223,7 @@ void MainTab::clearInfo()
ui.airTemperatureText->clear();
ui.airPressureText->clear();
ui.salinityText->clear();
+ ui.tagWidget->clear();
}
void MainTab::clearStats()
@@ -356,6 +365,11 @@ void MainTab::updateDiveInfo(int dive)
ui.timeLimits->setMaximum(get_time_string(stats_selection.longest_time.seconds, 0));
ui.timeLimits->setMinimum(get_time_string(stats_selection.shortest_time.seconds, 0));
+
+ char buf[1024];
+ taglist_get_tagstring(d->tag_list, buf, 1024);
+ ui.tagWidget->setText(QString(buf));
+
multiEditEquipmentPlaceholder = *d;
cylindersModel->setDive(&multiEditEquipmentPlaceholder);
weightModel->setDive(&multiEditEquipmentPlaceholder);
@@ -393,6 +407,7 @@ void MainTab::reload()
BuddyCompletionModel::instance()->updateModel();
LocationCompletionModel::instance()->updateModel();
DiveMasterCompletionModel::instance()->updateModel();
+ TagCompletionModel::instance()->updateModel();
}
void MainTab::acceptChanges()
@@ -423,7 +438,8 @@ void MainTab::acceptChanges()
notesBackup[curr].airtemp != ui.airtemp->text() ||
notesBackup[curr].watertemp != ui.watertemp->text() ||
notesBackup[curr].datetime != ui.dateTimeEdit->dateTime().toString(QString("M/d/yy h:mm")) ||
- notesBackup[curr].visibility != ui.rating->currentStars()) {
+ notesBackup[curr].visibility != ui.rating->currentStars() ||
+ notesBackup[curr].tags != ui.tagWidget->text()) {
mark_divelist_changed(TRUE);
}
if (notesBackup[curr].location != ui.location->text() ||
@@ -431,6 +447,9 @@ void MainTab::acceptChanges()
mainWindow()->globe()->reload();
}
+ if (notesBackup[curr].tags != ui.tagWidget->text())
+ saveTags();
+
if (cylindersModel->changed) {
mark_divelist_changed(TRUE);
Q_FOREACH (dive *d, notesBackup.keys()) {
@@ -480,6 +499,7 @@ void MainTab::resetPallete()
ui.airtemp->setPalette(p);
ui.watertemp->setPalette(p);
ui.dateTimeEdit->setPalette(p);
+ ui.tagWidget->setPalette(p);
}
#define EDIT_TEXT2(what, text) \
@@ -522,6 +542,7 @@ void MainTab::rejectChanges()
ui.airtemp->setText(notesBackup[curr].airtemp);
ui.watertemp->setText(notesBackup[curr].watertemp);
ui.dateTimeEdit->setDateTime(QDateTime::fromString(notesBackup[curr].datetime, QString("M/d/y h:mm")));
+ ui.tagWidget->setText(notesBackup[curr].tags);
struct dive *mydive;
for (int i = 0; i < dive_table.nr; i++) {
@@ -628,6 +649,21 @@ void MainTab::on_dateTimeEdit_dateTimeChanged(const QDateTime& datetime)
markChangedWidget(ui.dateTimeEdit);
}
+void MainTab::saveTags()
+{
+ EDIT_SELECTED_DIVES(
+ QString tag;
+ taglist_clear(mydive->tag_list);
+ foreach (tag, ui.tagWidget->getBlockStringList())
+ taglist_add_tag(mydive->tag_list, tag.toAscii().data());
+ );
+}
+
+void MainTab::on_tagWidget_textChanged()
+{
+ markChangedWidget(ui.tagWidget);
+}
+
void MainTab::on_location_textChanged(const QString& text)
{
if (editMode == NONE)
diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h
index afc30a079..22a705530 100644
--- a/qt-ui/maintab.h
+++ b/qt-ui/maintab.h
@@ -31,6 +31,7 @@ struct NotesBackup{
int rating;
int visibility;
QString divemaster;
+ QString tags;
cylinder_t cylinders[MAX_CYLINDERS];
weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS ];
};
@@ -40,6 +41,7 @@ struct Completers{
QCompleter *divemaster;
QCompleter *buddy;
QCompleter *suit;
+ QCompleter *tags;
};
class MainTab : public QTabWidget
@@ -73,6 +75,7 @@ public slots:
void on_dateTimeEdit_dateTimeChanged(const QDateTime& datetime);
void on_rating_valueChanged(int value);
void on_visibility_valueChanged(int value);
+ void on_tagWidget_textChanged();
void editCylinderWidget(const QModelIndex& index);
void editWeightWidget(const QModelIndex& index);
void addDiveStarted();
@@ -94,6 +97,7 @@ private:
Completers completers;
void resetPallete();
+ void saveTags();
QString printGPSCoords(int lat, int lon);
};
diff --git a/qt-ui/maintab.ui b/qt-ui/maintab.ui
index 3685f19ac..3e12d4c47 100644
--- a/qt-ui/maintab.ui
+++ b/qt-ui/maintab.ui
@@ -37,8 +37,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>513</width>
- <height>468</height>
+ <width>501</width>
+ <height>535</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
@@ -102,13 +102,6 @@
</item>
</layout>
</item>
- <item row="3" column="0">
- <widget class="QLabel" name="LocationLabel">
- <property name="text">
- <string>Location</string>
- </property>
- </widget>
- </item>
<item row="4" column="0" colspan="2">
<widget class="QLineEdit" name="location">
<property name="readOnly">
@@ -116,10 +109,17 @@
</property>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QLabel" name="CoordinatedLabel">
+ <item row="3" column="0">
+ <widget class="QLabel" name="LocationLabel">
<property name="text">
- <string>Coordinates</string>
+ <string>Location</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <widget class="QLabel" name="TagLabel">
+ <property name="text">
+ <string>Tags</string>
</property>
</widget>
</item>
@@ -130,10 +130,17 @@
</property>
</widget>
</item>
- <item row="7" column="0">
- <widget class="QLabel" name="DivemasterLabel">
+ <item row="8" column="0">
+ <widget class="QLineEdit" name="divemaster">
+ <property name="readOnly">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="CoordinatedLabel">
<property name="text">
- <string>Divemaster</string>
+ <string>Coordinates</string>
</property>
</widget>
</item>
@@ -144,15 +151,22 @@
</property>
</widget>
</item>
- <item row="8" column="0">
- <widget class="QLineEdit" name="divemaster">
+ <item row="8" column="1">
+ <widget class="QLineEdit" name="buddy">
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
- <item row="8" column="1">
- <widget class="QLineEdit" name="buddy">
+ <item row="7" column="0">
+ <widget class="QLabel" name="DivemasterLabel">
+ <property name="text">
+ <string>Divemaster</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="1">
+ <widget class="QLineEdit" name="suit">
<property name="readOnly">
<bool>false</bool>
</property>
@@ -176,6 +190,13 @@
</item>
</layout>
</item>
+ <item row="14" column="0" colspan="2">
+ <widget class="QTextEdit" name="notes">
+ <property name="readOnly">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
<item row="9" column="1">
<widget class="QLabel" name="SuitLabel">
<property name="text">
@@ -193,34 +214,45 @@
</item>
</layout>
</item>
- <item row="10" column="1">
- <widget class="QLineEdit" name="suit">
- <property name="readOnly">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="11" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="NotesLabel">
<property name="text">
<string>Notes</string>
</property>
</widget>
</item>
- <item row="12" column="0" colspan="2">
- <widget class="QTextEdit" name="notes">
- <property name="readOnly">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="13" column="0" colspan="2">
+ <item row="15" column="0" colspan="2">
<widget class="QDialogButtonBox" name="notesButtonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
+ <item row="12" column="0" colspan="2">
+ <widget class="TagWidget" name="tagWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="lineWrapMode">
+ <enum>QPlainTextEdit::NoWrap</enum>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</widget>
@@ -248,8 +280,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>513</width>
- <height>468</height>
+ <width>515</width>
+ <height>473</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_5">
@@ -335,8 +367,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>513</width>
- <height>468</height>
+ <width>515</width>
+ <height>473</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_6">
@@ -584,7 +616,7 @@
</widget>
</item>
<item row="4" column="0">
- <widget class="QGroupBox">
+ <widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Salinity</string>
</property>
@@ -642,8 +674,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>513</width>
- <height>468</height>
+ <width>515</width>
+ <height>473</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_7">
@@ -802,6 +834,11 @@
<header>tableview.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>TagWidget</class>
+ <extends>QPlainTextEdit</extends>
+ <header>qt-ui/tagwidget.h</header>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/qt-ui/tagwidget.cpp b/qt-ui/tagwidget.cpp
new file mode 100644
index 000000000..bcefe5704
--- /dev/null
+++ b/qt-ui/tagwidget.cpp
@@ -0,0 +1,135 @@
+#include "tagwidget.h"
+#include <QPair>
+#include <QDebug>
+
+TagWidget::TagWidget(QWidget *parent) : GroupedLineEdit(parent), m_completer(NULL)
+{
+ connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(reparse()));
+
+ addColor(QColor(0x00, 0xAE, 0xFF));
+ addColor(QColor(0x00, 0x78, 0xB0));
+}
+
+void TagWidget::setCompleter(QCompleter *completer)
+{
+ m_completer = completer;
+ m_completer->setWidget(this);
+ connect(m_completer, SIGNAL(activated(QString)), this, SLOT(completionSelected(QString)));
+}
+
+QPair<int,int> TagWidget::getCursorTagPosition() {
+ int i = 0, start = 0, end = 0;
+ /* Parse string near cursor */
+ i = cursorPosition();
+ while (--i > 0) {
+ if (text().at(i) == ',') {
+ if (i > 0 && text().at(i-1) != '\\') {
+ i++;
+ break;
+ }
+ }
+ }
+ start = i;
+ while (++i < text().length()) {
+ if (text().at(i) == ',') {
+ if (i > 0 && text().at(i-1) != '\\')
+ break;
+ }
+ }
+ end = i;
+ if (start < 0 || end < 0) {
+ start = 0;
+ end = 0;
+ }
+ return QPair<int,int>(start,end);
+}
+
+enum ParseState {FINDSTART, FINDEND};
+
+void TagWidget::highlight() {
+ int i = 0, start = 0, end = 0;
+ ParseState state = FINDEND;
+ removeAllBlocks();
+
+ while(i < text().length()) {
+ if (text().at(i) == ',') {
+ if (state == FINDSTART) {
+ /* Detect empty tags */
+ } else if (state == FINDEND) {
+ /* Found end of tag */
+ if (i > 1) {
+ if(text().at(i-1) != '\\') {
+ addBlock(start, end);
+ state = FINDSTART;
+ }
+ } else {
+ state = FINDSTART;
+ }
+ }
+ } else if (text().at(i) == ' ') {
+ /* Handled */
+ } else {
+ /* Found start of tag */
+ if (state == FINDSTART) {
+ state = FINDEND;
+ start = i;
+ } else if (state == FINDEND) {
+ end = i;
+ }
+ }
+ i++;
+ }
+ if (state == FINDEND) {
+ if (end < start)
+ end = text().length()-1;
+ if (text().length() > 0)
+ addBlock(start, end);
+ }
+}
+
+void TagWidget::reparse()
+{
+ highlight();
+ QPair<int,int> pos = getCursorTagPosition();
+ QString currentText;
+ if (pos.first >= 0 && pos.second > 0)
+ currentText = text().mid(pos.first, pos.second-pos.first).trimmed();
+ else
+ currentText = "";
+ if (m_completer) {
+ m_completer->setCompletionPrefix(currentText);
+ m_completer->complete();
+ }
+}
+
+void TagWidget::completionSelected(QString completion) {
+ QPair <int,int> pos;
+ pos = getCursorTagPosition();
+ if (pos.first >= 0 && pos.second > 0) {
+ setText(text().remove(pos.first, pos.second-pos.first).insert(pos.first, completion));
+ setCursorPosition(pos.first+completion.length());
+ }
+ else {
+ setText(completion.append(", "));
+ setCursorPosition(text().length());
+ }
+}
+
+void TagWidget::setCursorPosition(int position) {
+ blockSignals(true);
+ GroupedLineEdit::setCursorPosition(position);
+ blockSignals(false);
+}
+
+void TagWidget::setText(QString text) {
+ blockSignals(true);
+ GroupedLineEdit::setText(text);
+ blockSignals(false);
+ highlight();
+}
+
+void TagWidget::clear() {
+ blockSignals(true);
+ GroupedLineEdit::clear();
+ blockSignals(false);
+}
diff --git a/qt-ui/tagwidget.h b/qt-ui/tagwidget.h
new file mode 100644
index 000000000..ff19d7283
--- /dev/null
+++ b/qt-ui/tagwidget.h
@@ -0,0 +1,26 @@
+#ifndef __TAGWIDGET_H
+#define __TAGWIDGET_H
+
+#include "groupedlineedit.h"
+#include <QCompleter>
+#include <QPair>
+
+class TagWidget : public GroupedLineEdit
+{
+ Q_OBJECT
+public:
+ explicit TagWidget(QWidget *parent = 0);
+ void setCompleter(QCompleter *completer);
+ QPair<int, int> getCursorTagPosition();
+ void highlight();
+ void setText(QString text);
+ void clear();
+ void setCursorPosition(int position);
+public slots:
+ void reparse();
+ void completionSelected(QString);
+private:
+ QCompleter *m_completer;
+};
+
+#endif /* __TAGWIDGET_H */