mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Added a custom widget for tagging dives
A custom tag widget has been added to MainTab. Tags are seperated by a comma ",". The implementation supports escaping a comma by using "\,". While typing, the widget supports the user by suggesting tags using a QCompleter. Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
This commit is contained in:
parent
6fe8cb6521
commit
04cdfce782
10 changed files with 582 additions and 50 deletions
|
@ -12,6 +12,7 @@ CREATE_SINGLETON(BuddyCompletionModel);
|
||||||
CREATE_SINGLETON(DiveMasterCompletionModel);
|
CREATE_SINGLETON(DiveMasterCompletionModel);
|
||||||
CREATE_SINGLETON(LocationCompletionModel);
|
CREATE_SINGLETON(LocationCompletionModel);
|
||||||
CREATE_SINGLETON(SuitCompletionModel);
|
CREATE_SINGLETON(SuitCompletionModel);
|
||||||
|
CREATE_SINGLETON(TagCompletionModel);
|
||||||
|
|
||||||
#undef CREATE_SINGLETON
|
#undef CREATE_SINGLETON
|
||||||
|
|
||||||
|
@ -35,3 +36,15 @@ CREATE_UPDATE_METHOD(DiveMasterCompletionModel, divemaster);
|
||||||
CREATE_UPDATE_METHOD(LocationCompletionModel, location);
|
CREATE_UPDATE_METHOD(LocationCompletionModel, location);
|
||||||
CREATE_UPDATE_METHOD(SuitCompletionModel, suit);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -31,4 +31,11 @@ public:
|
||||||
void updateModel();
|
void updateModel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TagCompletionModel : public QStringListModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static TagCompletionModel* instance();
|
||||||
|
void updateModel();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
204
qt-ui/groupedlineedit.cpp
Normal file
204
qt-ui/groupedlineedit.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
66
qt-ui/groupedlineedit.h
Normal file
66
qt-ui/groupedlineedit.h
Normal file
|
@ -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
|
|
@ -58,6 +58,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
|
||||||
ui.airtemp->installEventFilter(this);
|
ui.airtemp->installEventFilter(this);
|
||||||
ui.watertemp->installEventFilter(this);
|
ui.watertemp->installEventFilter(this);
|
||||||
ui.dateTimeEdit->installEventFilter(this);
|
ui.dateTimeEdit->installEventFilter(this);
|
||||||
|
ui.tagWidget->installEventFilter(this);
|
||||||
|
|
||||||
QList<QObject *> statisticsTabWidgets = ui.statisticsTab->children();
|
QList<QObject *> statisticsTabWidgets = ui.statisticsTab->children();
|
||||||
Q_FOREACH(QObject* obj, statisticsTabWidgets) {
|
Q_FOREACH(QObject* obj, statisticsTabWidgets) {
|
||||||
|
@ -87,10 +88,12 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
|
||||||
completers.divemaster = new QCompleter(DiveMasterCompletionModel::instance(), ui.divemaster);
|
completers.divemaster = new QCompleter(DiveMasterCompletionModel::instance(), ui.divemaster);
|
||||||
completers.location = new QCompleter(LocationCompletionModel::instance(), ui.location);
|
completers.location = new QCompleter(LocationCompletionModel::instance(), ui.location);
|
||||||
completers.suit = new QCompleter(SuitCompletionModel::instance(), ui.suit);
|
completers.suit = new QCompleter(SuitCompletionModel::instance(), ui.suit);
|
||||||
|
completers.tags = new QCompleter(TagCompletionModel::instance(), ui.tagWidget);
|
||||||
ui.buddy->setCompleter(completers.buddy);
|
ui.buddy->setCompleter(completers.buddy);
|
||||||
ui.divemaster->setCompleter(completers.divemaster);
|
ui.divemaster->setCompleter(completers.divemaster);
|
||||||
ui.location->setCompleter(completers.location);
|
ui.location->setCompleter(completers.location);
|
||||||
ui.suit->setCompleter(completers.suit);
|
ui.suit->setCompleter(completers.suit);
|
||||||
|
ui.tagWidget->setCompleter(completers.tags);
|
||||||
|
|
||||||
setMinimumHeight(0);
|
setMinimumHeight(0);
|
||||||
setMinimumWidth(0);
|
setMinimumWidth(0);
|
||||||
|
@ -161,6 +164,9 @@ void MainTab::enableEdition(EditMode newEditMode)
|
||||||
notesBackup[mydive].airtemp = get_temperature_string(mydive->airtemp, true);
|
notesBackup[mydive].airtemp = get_temperature_string(mydive->airtemp, true);
|
||||||
notesBackup[mydive].watertemp = get_temperature_string(mydive->watertemp, 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"));
|
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?
|
// maybe this is a place for memset?
|
||||||
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
||||||
|
@ -182,7 +188,9 @@ bool MainTab::eventFilter(QObject* object, QEvent* event)
|
||||||
enableEdition();
|
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"));
|
tabBar()->setTabIcon(currentIndex(), QIcon(":warning"));
|
||||||
enableEdition();
|
enableEdition();
|
||||||
}
|
}
|
||||||
|
@ -215,6 +223,7 @@ void MainTab::clearInfo()
|
||||||
ui.airTemperatureText->clear();
|
ui.airTemperatureText->clear();
|
||||||
ui.airPressureText->clear();
|
ui.airPressureText->clear();
|
||||||
ui.salinityText->clear();
|
ui.salinityText->clear();
|
||||||
|
ui.tagWidget->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTab::clearStats()
|
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->setMaximum(get_time_string(stats_selection.longest_time.seconds, 0));
|
||||||
ui.timeLimits->setMinimum(get_time_string(stats_selection.shortest_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;
|
multiEditEquipmentPlaceholder = *d;
|
||||||
cylindersModel->setDive(&multiEditEquipmentPlaceholder);
|
cylindersModel->setDive(&multiEditEquipmentPlaceholder);
|
||||||
weightModel->setDive(&multiEditEquipmentPlaceholder);
|
weightModel->setDive(&multiEditEquipmentPlaceholder);
|
||||||
|
@ -393,6 +407,7 @@ void MainTab::reload()
|
||||||
BuddyCompletionModel::instance()->updateModel();
|
BuddyCompletionModel::instance()->updateModel();
|
||||||
LocationCompletionModel::instance()->updateModel();
|
LocationCompletionModel::instance()->updateModel();
|
||||||
DiveMasterCompletionModel::instance()->updateModel();
|
DiveMasterCompletionModel::instance()->updateModel();
|
||||||
|
TagCompletionModel::instance()->updateModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTab::acceptChanges()
|
void MainTab::acceptChanges()
|
||||||
|
@ -423,7 +438,8 @@ void MainTab::acceptChanges()
|
||||||
notesBackup[curr].airtemp != ui.airtemp->text() ||
|
notesBackup[curr].airtemp != ui.airtemp->text() ||
|
||||||
notesBackup[curr].watertemp != ui.watertemp->text() ||
|
notesBackup[curr].watertemp != ui.watertemp->text() ||
|
||||||
notesBackup[curr].datetime != ui.dateTimeEdit->dateTime().toString(QString("M/d/yy h:mm")) ||
|
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);
|
mark_divelist_changed(TRUE);
|
||||||
}
|
}
|
||||||
if (notesBackup[curr].location != ui.location->text() ||
|
if (notesBackup[curr].location != ui.location->text() ||
|
||||||
|
@ -431,6 +447,9 @@ void MainTab::acceptChanges()
|
||||||
mainWindow()->globe()->reload();
|
mainWindow()->globe()->reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notesBackup[curr].tags != ui.tagWidget->text())
|
||||||
|
saveTags();
|
||||||
|
|
||||||
if (cylindersModel->changed) {
|
if (cylindersModel->changed) {
|
||||||
mark_divelist_changed(TRUE);
|
mark_divelist_changed(TRUE);
|
||||||
Q_FOREACH (dive *d, notesBackup.keys()) {
|
Q_FOREACH (dive *d, notesBackup.keys()) {
|
||||||
|
@ -480,6 +499,7 @@ void MainTab::resetPallete()
|
||||||
ui.airtemp->setPalette(p);
|
ui.airtemp->setPalette(p);
|
||||||
ui.watertemp->setPalette(p);
|
ui.watertemp->setPalette(p);
|
||||||
ui.dateTimeEdit->setPalette(p);
|
ui.dateTimeEdit->setPalette(p);
|
||||||
|
ui.tagWidget->setPalette(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EDIT_TEXT2(what, text) \
|
#define EDIT_TEXT2(what, text) \
|
||||||
|
@ -522,6 +542,7 @@ void MainTab::rejectChanges()
|
||||||
ui.airtemp->setText(notesBackup[curr].airtemp);
|
ui.airtemp->setText(notesBackup[curr].airtemp);
|
||||||
ui.watertemp->setText(notesBackup[curr].watertemp);
|
ui.watertemp->setText(notesBackup[curr].watertemp);
|
||||||
ui.dateTimeEdit->setDateTime(QDateTime::fromString(notesBackup[curr].datetime, QString("M/d/y h:mm")));
|
ui.dateTimeEdit->setDateTime(QDateTime::fromString(notesBackup[curr].datetime, QString("M/d/y h:mm")));
|
||||||
|
ui.tagWidget->setText(notesBackup[curr].tags);
|
||||||
|
|
||||||
struct dive *mydive;
|
struct dive *mydive;
|
||||||
for (int i = 0; i < dive_table.nr; i++) {
|
for (int i = 0; i < dive_table.nr; i++) {
|
||||||
|
@ -628,6 +649,21 @@ void MainTab::on_dateTimeEdit_dateTimeChanged(const QDateTime& datetime)
|
||||||
markChangedWidget(ui.dateTimeEdit);
|
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)
|
void MainTab::on_location_textChanged(const QString& text)
|
||||||
{
|
{
|
||||||
if (editMode == NONE)
|
if (editMode == NONE)
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct NotesBackup{
|
||||||
int rating;
|
int rating;
|
||||||
int visibility;
|
int visibility;
|
||||||
QString divemaster;
|
QString divemaster;
|
||||||
|
QString tags;
|
||||||
cylinder_t cylinders[MAX_CYLINDERS];
|
cylinder_t cylinders[MAX_CYLINDERS];
|
||||||
weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS ];
|
weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS ];
|
||||||
};
|
};
|
||||||
|
@ -40,6 +41,7 @@ struct Completers{
|
||||||
QCompleter *divemaster;
|
QCompleter *divemaster;
|
||||||
QCompleter *buddy;
|
QCompleter *buddy;
|
||||||
QCompleter *suit;
|
QCompleter *suit;
|
||||||
|
QCompleter *tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MainTab : public QTabWidget
|
class MainTab : public QTabWidget
|
||||||
|
@ -73,6 +75,7 @@ public slots:
|
||||||
void on_dateTimeEdit_dateTimeChanged(const QDateTime& datetime);
|
void on_dateTimeEdit_dateTimeChanged(const QDateTime& datetime);
|
||||||
void on_rating_valueChanged(int value);
|
void on_rating_valueChanged(int value);
|
||||||
void on_visibility_valueChanged(int value);
|
void on_visibility_valueChanged(int value);
|
||||||
|
void on_tagWidget_textChanged();
|
||||||
void editCylinderWidget(const QModelIndex& index);
|
void editCylinderWidget(const QModelIndex& index);
|
||||||
void editWeightWidget(const QModelIndex& index);
|
void editWeightWidget(const QModelIndex& index);
|
||||||
void addDiveStarted();
|
void addDiveStarted();
|
||||||
|
@ -94,6 +97,7 @@ private:
|
||||||
|
|
||||||
Completers completers;
|
Completers completers;
|
||||||
void resetPallete();
|
void resetPallete();
|
||||||
|
void saveTags();
|
||||||
QString printGPSCoords(int lat, int lon);
|
QString printGPSCoords(int lat, int lon);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
127
qt-ui/maintab.ui
127
qt-ui/maintab.ui
|
@ -37,8 +37,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>513</width>
|
<width>501</width>
|
||||||
<height>468</height>
|
<height>535</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
@ -102,6 +102,13 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0" colspan="2">
|
||||||
|
<widget class="QLineEdit" name="location">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="LocationLabel">
|
<widget class="QLabel" name="LocationLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -109,8 +116,22 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0" colspan="2">
|
<item row="11" column="0">
|
||||||
<widget class="QLineEdit" name="location">
|
<widget class="QLabel" name="TagLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tags</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0" colspan="2">
|
||||||
|
<widget class="QLineEdit" name="coordinates">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLineEdit" name="divemaster">
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -123,8 +144,15 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" colspan="2">
|
<item row="7" column="1">
|
||||||
<widget class="QLineEdit" name="coordinates">
|
<widget class="QLabel" name="BuddyLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Buddy</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QLineEdit" name="buddy">
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -137,22 +165,8 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QLabel" name="BuddyLabel">
|
<widget class="QLineEdit" name="suit">
|
||||||
<property name="text">
|
|
||||||
<string>Buddy</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLineEdit" name="divemaster">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QLineEdit" name="buddy">
|
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -176,6 +190,13 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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">
|
<item row="9" column="1">
|
||||||
<widget class="QLabel" name="SuitLabel">
|
<widget class="QLabel" name="SuitLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -193,34 +214,45 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="1">
|
<item row="13" column="0">
|
||||||
<widget class="QLineEdit" name="suit">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="0">
|
|
||||||
<widget class="QLabel" name="NotesLabel">
|
<widget class="QLabel" name="NotesLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Notes</string>
|
<string>Notes</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="0" colspan="2">
|
<item row="15" 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">
|
|
||||||
<widget class="QDialogButtonBox" name="notesButtonBox">
|
<widget class="QDialogButtonBox" name="notesButtonBox">
|
||||||
<property name="standardButtons">
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -248,8 +280,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>513</width>
|
<width>515</width>
|
||||||
<height>468</height>
|
<height>473</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_5">
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
|
@ -335,8 +367,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>513</width>
|
<width>515</width>
|
||||||
<height>468</height>
|
<height>473</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_6">
|
<layout class="QGridLayout" name="gridLayout_6">
|
||||||
|
@ -584,7 +616,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QGroupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Salinity</string>
|
<string>Salinity</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -642,8 +674,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>513</width>
|
<width>515</width>
|
||||||
<height>468</height>
|
<height>473</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_7">
|
<layout class="QGridLayout" name="gridLayout_7">
|
||||||
|
@ -802,6 +834,11 @@
|
||||||
<header>tableview.h</header>
|
<header>tableview.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>TagWidget</class>
|
||||||
|
<extends>QPlainTextEdit</extends>
|
||||||
|
<header>qt-ui/tagwidget.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
135
qt-ui/tagwidget.cpp
Normal file
135
qt-ui/tagwidget.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
26
qt-ui/tagwidget.h
Normal file
26
qt-ui/tagwidget.h
Normal file
|
@ -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 */
|
|
@ -56,7 +56,9 @@ HEADERS = \
|
||||||
subsurfacestartup.h \
|
subsurfacestartup.h \
|
||||||
uemis.h \
|
uemis.h \
|
||||||
webservice.h \
|
webservice.h \
|
||||||
qt-ui/csvimportdialog.h
|
qt-ui/csvimportdialog.h \
|
||||||
|
qt-ui/tagwidget.h \
|
||||||
|
qt-ui/groupedlineedit.h
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
deco.c \
|
deco.c \
|
||||||
|
@ -103,7 +105,9 @@ SOURCES = \
|
||||||
time.c \
|
time.c \
|
||||||
uemis.c \
|
uemis.c \
|
||||||
uemis-downloader.c \
|
uemis-downloader.c \
|
||||||
qt-ui/csvimportdialog.cpp
|
qt-ui/csvimportdialog.cpp \
|
||||||
|
qt-ui/tagwidget.cpp \
|
||||||
|
qt-ui/groupedlineedit.cpp
|
||||||
|
|
||||||
linux*: SOURCES += linux.c
|
linux*: SOURCES += linux.c
|
||||||
mac: SOURCES += macos.c
|
mac: SOURCES += macos.c
|
||||||
|
|
Loading…
Reference in a new issue