mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-23 22:49:37 -05:00
515 lines
13 KiB
C++
515 lines
13 KiB
C++
|
/***************************************************************************
|
||
|
* Copyright (C) 2004-2005 Artur Wiebe *
|
||
|
* wibix@gmx.de *
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
* This program 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 General Public License for more details. *
|
||
|
* *
|
||
|
* You should have received a copy of the GNU General Public License *
|
||
|
* along with this program; if not, write to the *
|
||
|
* Free Software Foundation, Inc., *
|
||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||
|
***************************************************************************/
|
||
|
#include <QLayout>
|
||
|
#include <QDebug>
|
||
|
#include <QProgressDialog>
|
||
|
#include <QHeaderView>
|
||
|
#include <QInputDialog>
|
||
|
#include <QLineEdit>
|
||
|
|
||
|
#include "history.h"
|
||
|
#include "common.h"
|
||
|
|
||
|
|
||
|
|
||
|
#define COL_TAG_NR 0 // m_tags, this col is hidden.
|
||
|
#define COL_TAG_NAME 1
|
||
|
#define COL_TAG_VAL 2
|
||
|
|
||
|
#define COL_MOVE_NR 0 // m_movelist
|
||
|
#define COL_MOVE 1
|
||
|
#define COL_MOVE_COMM 2
|
||
|
|
||
|
|
||
|
myHistory::myHistory(QWidget* parent)
|
||
|
: QFrame(parent)
|
||
|
{
|
||
|
setFixedWidth(240);
|
||
|
|
||
|
m_gamelist = new QComboBox(this);
|
||
|
connect(m_gamelist, SIGNAL(activated(int)),
|
||
|
this, SLOT(slot_game_selected(int)));
|
||
|
|
||
|
m_taglist = new QTreeWidget(this);
|
||
|
m_taglist->setColumnCount(3);
|
||
|
m_taglist->header()->hide();
|
||
|
m_taglist->setColumnHidden(COL_TAG_NR, true);
|
||
|
// m_taglist->header()->setStretchLastSection(true);
|
||
|
// m_taglist->header()->setResizeMode(QHeaderView::Stretch);
|
||
|
m_taglist->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||
|
connect(m_taglist, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
|
||
|
this, SLOT(slot_modify_tag(QTreeWidgetItem*, int)));
|
||
|
|
||
|
m_movelist = new QTreeWidget(this);
|
||
|
m_movelist->setColumnCount(3);
|
||
|
m_movelist->header()->setStretchLastSection(true);
|
||
|
m_movelist->header()->setMovable(false);
|
||
|
m_movelist->setRootIsDecorated(false);
|
||
|
QStringList header;
|
||
|
header << "#" << tr("Move") << tr("Comment");
|
||
|
m_movelist->setHeaderLabels(header);
|
||
|
//
|
||
|
connect(m_movelist, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
|
||
|
this, SLOT(slot_modify_comment(QTreeWidgetItem*, int)));
|
||
|
connect(m_movelist,
|
||
|
SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
|
||
|
this,
|
||
|
SLOT(slot_move(QTreeWidgetItem*, QTreeWidgetItem*)));
|
||
|
|
||
|
// history
|
||
|
/*
|
||
|
gameUndo = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this);
|
||
|
connect(gameUndo, SIGNAL(triggered()), m_view, SLOT(slotUndo()));
|
||
|
|
||
|
gameRedo = new QAction(QIcon(":/icons/redo.png"), tr("&Redo"), this);
|
||
|
connect(gameRedo, SIGNAL(triggered()), m_view, SLOT(slotRedo()));
|
||
|
|
||
|
gameContinue = new QAction(QIcon(":/icons/continue.png"),
|
||
|
tr("&Continue"), this);
|
||
|
connect(gameContinue, SIGNAL(triggered()), m_view, SLOT(slotContinue()));
|
||
|
|
||
|
|
||
|
*/
|
||
|
m_mode_icon = new QLabel(this);
|
||
|
m_mode_icon->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
||
|
|
||
|
m_undo = new QToolButton(this);
|
||
|
m_undo->setIcon(QIcon(":/icons/undo.png"));
|
||
|
m_undo->setToolTip(tr("Undo"));
|
||
|
connect(m_undo, SIGNAL(clicked()), this, SLOT(slot_undo()));
|
||
|
|
||
|
m_redo = new QToolButton(this);
|
||
|
m_redo->setIcon(QIcon(":/icons/redo.png"));
|
||
|
m_redo->setToolTip(tr("Redo"));
|
||
|
connect(m_redo, SIGNAL(clicked()), this, SLOT(slot_redo()));
|
||
|
|
||
|
m_cont = new QToolButton(this);
|
||
|
m_cont->setIcon(QIcon(":/icons/continue.png"));
|
||
|
m_cont->setToolTip(tr("Continue"));
|
||
|
connect(m_cont, SIGNAL(clicked()), this, SLOT(slot_continue()));
|
||
|
|
||
|
m_current = new QLabel(this);
|
||
|
|
||
|
QHBoxLayout* history = new QHBoxLayout();
|
||
|
history->addWidget(m_mode_icon);
|
||
|
//TODO history->addStretch();
|
||
|
history->addWidget(m_undo);
|
||
|
history->addWidget(m_redo);
|
||
|
history->addWidget(m_cont);
|
||
|
history->addStretch();
|
||
|
history->addWidget(m_current);
|
||
|
|
||
|
// layout
|
||
|
QVBoxLayout* vb = new QVBoxLayout(this);
|
||
|
vb->setMargin(0);
|
||
|
vb->addWidget(m_gamelist, 0);
|
||
|
vb->addWidget(m_taglist, 2);
|
||
|
vb->addWidget(m_movelist, 4);
|
||
|
vb->addLayout(history);
|
||
|
|
||
|
/*
|
||
|
* other stuff
|
||
|
*/
|
||
|
m_pdn = new Pdn();
|
||
|
m_disable_moves = false;
|
||
|
//
|
||
|
m_paused = true; // little hack ensures a mode change.
|
||
|
m_freeplace = false;
|
||
|
set_mode(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
myHistory::~myHistory()
|
||
|
{
|
||
|
delete m_pdn;
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::clear()
|
||
|
{
|
||
|
m_gamelist->clear();
|
||
|
m_pdn->clear();
|
||
|
m_taglist->clear();
|
||
|
m_movelist->clear();
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::setTag(PdnGame::Tag tag, const QString& val)
|
||
|
{
|
||
|
QTreeWidgetItem* item = 0;
|
||
|
QList<QTreeWidgetItem*> item_list = m_taglist->findItems(
|
||
|
tag_to_string(tag), Qt::MatchExactly, COL_TAG_NAME);
|
||
|
if(item_list.count()) {
|
||
|
if(item_list.count() == 1)
|
||
|
item = item_list[0];
|
||
|
else
|
||
|
qDebug() << __PRETTY_FUNCTION__ << "ERR";
|
||
|
}
|
||
|
|
||
|
if(item) {
|
||
|
item->setText(COL_TAG_VAL, val);
|
||
|
} else {
|
||
|
item = new QTreeWidgetItem(m_taglist);
|
||
|
item->setText(COL_TAG_NR, QString::number(tag));
|
||
|
item->setText(COL_TAG_NAME, tag_to_string(tag));
|
||
|
item->setText(COL_TAG_VAL, val);
|
||
|
}
|
||
|
|
||
|
if(tag==PdnGame::Type) {
|
||
|
item->setText(COL_TAG_VAL, val + " ("
|
||
|
+ typeToString(QString("%1").arg(val).toInt())
|
||
|
+ ")");
|
||
|
}
|
||
|
|
||
|
m_game->set(tag, val);
|
||
|
//TODO m_taglist->resizeColumnToContents(COL_TAG_NAME);
|
||
|
}
|
||
|
|
||
|
|
||
|
QString myHistory::getTag(PdnGame::Tag tag)
|
||
|
{
|
||
|
QList<QTreeWidgetItem*> item_list = m_taglist->findItems(
|
||
|
tag_to_string(tag), Qt::MatchExactly, COL_TAG_NAME);
|
||
|
if(item_list.count() == 1)
|
||
|
return item_list[0]->text(COL_TAG_VAL);
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
|
||
|
QString myHistory::tag_to_string(PdnGame::Tag tag)
|
||
|
{
|
||
|
switch(tag) {
|
||
|
case PdnGame::Date: return /*tr(*/"Date";//);
|
||
|
case PdnGame::Site: return /*tr(*/"Site";//);
|
||
|
case PdnGame::Type: return /*tr(*/"Type";//);
|
||
|
case PdnGame::Event: return /*tr(*/"Event";//);
|
||
|
case PdnGame::Round: return /*tr(*/"Round";//);
|
||
|
case PdnGame::White: return /*tr(*/"White";//);
|
||
|
case PdnGame::Black: return /*tr(*/"Black";//);
|
||
|
case PdnGame::Result: return /*tr(*/"Result";//);
|
||
|
}
|
||
|
|
||
|
return "Site"; // FIXME
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::appendMove(const QString& text, const QString& comm)
|
||
|
{
|
||
|
m_disable_moves = true;
|
||
|
|
||
|
QTreeWidgetItem* new_item = new QTreeWidgetItem(m_movelist);
|
||
|
new_item->setText(COL_MOVE, text);
|
||
|
new_item->setText(COL_MOVE_COMM, comm);
|
||
|
|
||
|
int move_nr = (m_movelist->topLevelItemCount() - 2) / 2;
|
||
|
PdnMove* m = m_game->getMove(move_nr);
|
||
|
|
||
|
if(m_movelist->topLevelItemCount()%2) {
|
||
|
m->m_second = text;
|
||
|
m->m_comsecond = comm;
|
||
|
} else {
|
||
|
new_item->setText(COL_MOVE_NR, QString("%1.").arg(move_nr+1));
|
||
|
m->m_first = text;
|
||
|
m->m_comfirst = comm;
|
||
|
}
|
||
|
|
||
|
m_movelist->setCurrentItem(new_item);
|
||
|
m_movelist->scrollToItem(new_item);
|
||
|
|
||
|
// TODO
|
||
|
m_movelist->resizeColumnToContents(COL_MOVE_NR);
|
||
|
|
||
|
m_disable_moves = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::slot_modify_comment(QTreeWidgetItem* item, int)
|
||
|
{
|
||
|
if(!item || item==m_movelist->topLevelItem(0) || m_paused)
|
||
|
return;
|
||
|
|
||
|
bool ok;
|
||
|
QString new_text = QInputDialog::getText(this, tr("Set Comment"),//FIXME
|
||
|
tr("Comment")+":", QLineEdit::Normal, item->text(COL_MOVE_COMM),
|
||
|
&ok);
|
||
|
if(!ok)
|
||
|
return;
|
||
|
|
||
|
new_text.remove('{');
|
||
|
new_text.remove('}');
|
||
|
if(new_text != item->text(COL_MOVE_COMM)) {
|
||
|
// gui
|
||
|
item->setText(COL_MOVE_COMM, new_text);
|
||
|
|
||
|
// pdn
|
||
|
int index = m_movelist->indexOfTopLevelItem(item);
|
||
|
PdnMove* move = m_game->getMove((index - 1) / 2);
|
||
|
if(index%2==1)
|
||
|
move->m_comfirst = new_text;
|
||
|
else
|
||
|
move->m_comsecond = new_text;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::slot_modify_tag(QTreeWidgetItem* item, int/* col*/)
|
||
|
{
|
||
|
if(!item || m_paused)
|
||
|
return;
|
||
|
|
||
|
PdnGame::Tag tag =(PdnGame::Tag)item->text(COL_TAG_NR).toUInt();
|
||
|
if(tag==PdnGame::Type) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool ok;
|
||
|
QString new_text = QInputDialog::getText(this, tr("Set Tag"),//FIXME
|
||
|
tr("Tag")+":", QLineEdit::Normal, item->text(COL_TAG_VAL), &ok);
|
||
|
if(!ok)
|
||
|
return;
|
||
|
|
||
|
new_text.remove('"');
|
||
|
new_text.remove('[');
|
||
|
new_text.remove(']');
|
||
|
|
||
|
if(new_text != item->text(COL_TAG_VAL)) {
|
||
|
item->setText(COL_TAG_VAL, new_text);
|
||
|
m_game->set(tag, new_text);
|
||
|
if(tag==PdnGame::Event)
|
||
|
m_gamelist->setItemText(m_gamelist->currentIndex(),
|
||
|
new_text);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool myHistory::openPdn(const QString& filename, QString& log_text)
|
||
|
{
|
||
|
if(!m_pdn->open(filename, this, tr("Reading file..."), log_text)) {
|
||
|
set_mode(false);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
set_mode(true);
|
||
|
|
||
|
m_gamelist->clear();
|
||
|
m_movelist->clear();
|
||
|
m_taglist->clear();
|
||
|
|
||
|
QProgressDialog progress(this);
|
||
|
progress.setModal(true);
|
||
|
progress.setLabelText(tr("Importing games..."));
|
||
|
progress.setRange(0, m_pdn->count());
|
||
|
progress.setMinimumDuration(0);
|
||
|
|
||
|
for(int i=0; i<m_pdn->count(); ++i) {
|
||
|
if((i%10)==0)
|
||
|
progress.setValue(i);
|
||
|
m_gamelist->insertItem(i, m_pdn->game(i)->get(PdnGame::Event));
|
||
|
}
|
||
|
|
||
|
slot_game_selected(0);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool myHistory::savePdn(const QString& fn)
|
||
|
{
|
||
|
return m_pdn->save(fn);
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::slot_game_selected(int index)
|
||
|
{
|
||
|
if(index>=m_pdn->count()) {
|
||
|
qDebug() << __PRETTY_FUNCTION__ << "Index" << index
|
||
|
<< "out of range >=" << m_pdn->count();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_game = m_pdn->game(index);
|
||
|
m_movelist->clear();
|
||
|
|
||
|
QTreeWidgetItem* root = new QTreeWidgetItem(m_movelist);
|
||
|
for(int i=0; i<m_game->movesCount(); ++i) {
|
||
|
PdnMove* m = m_game->getMove(i);
|
||
|
|
||
|
appendMove(m->m_first, m->m_comfirst);
|
||
|
if(m->m_second.length())
|
||
|
appendMove(m->m_second, m->m_comsecond);
|
||
|
}
|
||
|
|
||
|
setTag(PdnGame::Site, m_game->get(PdnGame::Site));
|
||
|
setTag(PdnGame::Black, m_game->get(PdnGame::Black));
|
||
|
setTag(PdnGame::White, m_game->get(PdnGame::White));
|
||
|
setTag(PdnGame::Result, m_game->get(PdnGame::Result));
|
||
|
setTag(PdnGame::Date, m_game->get(PdnGame::Date));
|
||
|
setTag(PdnGame::Site, m_game->get(PdnGame::Site));
|
||
|
setTag(PdnGame::Type, m_game->get(PdnGame::Type));
|
||
|
setTag(PdnGame::Round, m_game->get(PdnGame::Round));
|
||
|
setTag(PdnGame::Event, m_game->get(PdnGame::Event));
|
||
|
|
||
|
// signal to view
|
||
|
if(m_paused && !m_freeplace) {
|
||
|
emit previewGame(m_game->get(PdnGame::Type).toInt());
|
||
|
}
|
||
|
|
||
|
m_movelist->setCurrentItem(root);
|
||
|
slot_move(root, 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::newPdn(const QString& event, bool freeplace)
|
||
|
{
|
||
|
m_freeplace = freeplace;
|
||
|
m_paused = !m_freeplace; // FIXME - needed to force view update.
|
||
|
set_mode(m_freeplace);
|
||
|
|
||
|
PdnGame* game = m_pdn->newGame();
|
||
|
game->set(PdnGame::Event, event);
|
||
|
|
||
|
int index = m_gamelist->count();
|
||
|
m_gamelist->insertItem(index, event);
|
||
|
m_gamelist->setCurrentIndex(index);
|
||
|
|
||
|
slot_game_selected(index);
|
||
|
}
|
||
|
|
||
|
|
||
|
QString myHistory::typeToString(int type)
|
||
|
{
|
||
|
switch(type) {
|
||
|
case ENGLISH: return tr("English draughts");
|
||
|
case RUSSIAN: return tr("Russian draughts");
|
||
|
};
|
||
|
return tr("Unknown game type");
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::set_mode(bool paused)
|
||
|
{
|
||
|
if(m_paused != paused) {
|
||
|
m_paused = paused;
|
||
|
|
||
|
if(m_paused) {
|
||
|
if(m_freeplace) {
|
||
|
m_mode_icon->setPixmap(QPixmap(":/icons/freeplace.png"));
|
||
|
m_mode_icon->setToolTip(tr("Free Placement Mode"));
|
||
|
} else {
|
||
|
m_mode_icon->setPixmap(QPixmap(":/icons/paused.png"));
|
||
|
m_mode_icon->setToolTip(tr("Paused Mode"));
|
||
|
}
|
||
|
} else {
|
||
|
m_mode_icon->setPixmap(QPixmap(":/icons/logo.png"));
|
||
|
m_mode_icon->setToolTip(tr("Play Mode"));
|
||
|
}
|
||
|
|
||
|
m_gamelist->setEnabled(m_paused);
|
||
|
//FIXME m_movelist->setEnabled(yes);
|
||
|
|
||
|
emit newMode(m_paused, m_freeplace);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::slot_move(QTreeWidgetItem* item, QTreeWidgetItem*)
|
||
|
{
|
||
|
// update history buttons.
|
||
|
bool curr_is_first =
|
||
|
(m_movelist->topLevelItem(0) == m_movelist->currentItem());
|
||
|
bool curr_is_last =
|
||
|
(m_movelist->indexOfTopLevelItem(m_movelist->currentItem())
|
||
|
== m_movelist->topLevelItemCount()-1);
|
||
|
|
||
|
m_undo->setEnabled(!curr_is_first);
|
||
|
m_redo->setEnabled(!curr_is_last);
|
||
|
m_cont->setEnabled(m_paused);
|
||
|
|
||
|
|
||
|
// process
|
||
|
if(!item || !m_paused || m_disable_moves)
|
||
|
return;
|
||
|
|
||
|
do_moves();
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::history_undo(bool move_backwards)
|
||
|
{
|
||
|
int next = m_movelist->indexOfTopLevelItem(m_movelist->currentItem())
|
||
|
+ (move_backwards ? -1 : +1);
|
||
|
|
||
|
if(next>=0 && next<m_movelist->topLevelItemCount())
|
||
|
m_movelist->setCurrentItem(m_movelist->topLevelItem(next));
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::do_moves()
|
||
|
{
|
||
|
QString moves;
|
||
|
QTreeWidgetItem* item = m_movelist->currentItem();
|
||
|
for(int i=0; i<m_movelist->topLevelItemCount(); ++i) {
|
||
|
QTreeWidgetItem* cur = m_movelist->topLevelItem(i);
|
||
|
moves += cur->text(COL_MOVE) + MOVE_SPLIT;
|
||
|
if(m_movelist->topLevelItem(i)==item)
|
||
|
break;
|
||
|
}
|
||
|
emit applyMoves(moves);
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::delete_moves()
|
||
|
{
|
||
|
int curr = m_movelist->indexOfTopLevelItem(m_movelist->currentItem());
|
||
|
while(m_movelist->topLevelItemCount() > curr+1) {
|
||
|
delete m_movelist->topLevelItem(
|
||
|
m_movelist->topLevelItemCount()-1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::slot_undo()
|
||
|
{
|
||
|
set_mode(true);
|
||
|
history_undo(true);
|
||
|
do_moves();
|
||
|
}
|
||
|
|
||
|
void myHistory::slot_redo()
|
||
|
{
|
||
|
set_mode(true);
|
||
|
history_undo(false);
|
||
|
do_moves();
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::slot_continue()
|
||
|
{
|
||
|
delete_moves();
|
||
|
set_mode(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
void myHistory::slotWorking(bool b)
|
||
|
{
|
||
|
setEnabled(!b);
|
||
|
}
|
||
|
|