/* Marcion
Copyright (C) 2009 - 2011 Milan Konvicka
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; version 2 of the License.
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 */
#include "mimages.h"
CMImages::CMImages(CMessages * const messages,
QWidget *parent) :
QWidget(parent),
ui(new Ui::CMImages),
popup(),
messages(messages),
bt_action(false)
{
ui->setupUi(this);
ui->iwImg->drawarea()->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
ui->iwImg->drawarea()->setImageMode(CMImage::Map);
//layH->addWidget(&drawarea);
ui->treeImages->hideColumn(1);
ui->treeImages->hideColumn(2);
ui->treeImages->hideColumn(3);
ui->splitter->setStretchFactor(0,0);
ui->splitter->setStretchFactor(1,1);
QList<int> li;
li << 1 << 1;
ui->splitter->setSizes(li);
open_map=popup.addAction(tr("view map"));
popup.addSeparator();
expand=popup.addAction(tr("expand"));
collapse=popup.addAction(tr("collapse"));
expand_all=popup.addAction(tr("expand all"));
collapse_all=popup.addAction(tr("collapse all"));
popup.addSeparator();
del_map=popup.addAction(tr("delete item(s)"));
bkp_map=popup.addAction(tr("backup collection"));
import_col=popup.addAction(tr("import collection"));
popup.addSeparator();
reload_maps=popup.addAction(QIcon(":/new/icons/icons/refresh.png"),tr("reload tree"));
popup.addSeparator();
create_col=popup.addAction(tr("create collection"));
add_map=popup.addAction(tr("add map"));
edit_cm=popup.addAction(tr("edit item"));
imp_img=popup.addAction(tr("import image"));
reorder_maps=popup.addAction(tr("reorder maps"));
map_longlat=popup.addAction(tr("set map area"));
if(!m_sett()->isCopticEditable())
{
create_col->setEnabled(false);
add_map->setEnabled(false);
edit_cm->setEnabled(false);
imp_img->setEnabled(false);
reorder_maps->setEnabled(false);
map_longlat->setEnabled(false);
}
loadData();
IC_SIZES
}
bool CMImages::loadData()
{
ui->treeImages->clear();
QString query("select `image_collection`.`id`,`image_collection`.`name`,`image_collection`.`dirname`,`image`.`id`,`image`.`name`,`image`.`filename` from `image_collection` left outer join `image` on `image_collection`.`id`=`image`.`collection` order by `image_collection`.`name`,`image`.`ord`");
CMySql q(query);
messages->MsgMsg(tr("executing query '")+query+"' ...");
if(!q.exec())
{
messages->MsgErr(q.lastError());
return false;
}
unsigned int lastid(0);
QTreeWidgetItem * i(0);
while(q.next())
{
unsigned int currid(q.value(0).toUInt());
if(lastid!=currid)
{
if(i)
ui->treeImages->addTopLevelItem(i);
i=new QTreeWidgetItem(0);
QString n(q.value(1));
i->setText(0,n);
i->setToolTip(0,n);
i->setText(1,q.value(2));
i->setText(2,"collection");
i->setText(3,q.value(0));
lastid=currid;
}
QTreeWidgetItem * chi=new QTreeWidgetItem(0);
if(!q.isNULL(3))
{
QString n(q.value(4));
chi->setText(0,n);
chi->setToolTip(0,n);
chi->setText(1,q.value(5));
chi->setText(2,"image");
chi->setText(3,q.value(3));
i->addChild(chi);
}
}
if(i)
ui->treeImages->addTopLevelItem(i);
messages->MsgOk();
return true;
}
void CMImages::on_treeImages_itemDoubleClicked(QTreeWidgetItem* item, int )
{
if(item)
if(item->text(2)=="image")
{
USE_CLEAN_WAIT
QString ct(item->parent()->text(0)),
bt(item->text(0)),
cf(item->parent()->text(1)),
bf(item->text(1)),
imgid(item->text(3));
setWindowTitle(tr("Maps - ")+ct+", "+bt);
QDir wdir;
QString dname(QDir::toNativeSeparators("data/maps/"+cf));
QString fname(dname+QDir::separator()+bf);
messages->MsgMsg(tr("loading '")+fname+"' ...");
if(!wdir.exists(fname))
{
messages->MsgMsg("'"+fname+tr("' don't exist, retrieving from database ..."));
if(!QDir(dname).exists())
{
messages->MsgMsg(tr("directory '")+dname+tr("' don't exist, creating ..."));
if(!wdir.mkpath(dname))
{
messages->MsgErr(tr("cannot create directory"));
return;
}
}
QString query("select `image`,length(`image`) from `image` where `id`="+imgid);
CMySql q(query);
messages->MsgMsg(tr("executing query '")+query+"' ...");
if(!q.exec())
{
messages->MsgErr(q.lastError());
return;
}
if(!q.first())
{
messages->MsgErr(tr("something wrong"));
return;
}
if(q.isNULL(0))
{
messages->MsgErr(tr("image is NULL, import it or delete"));
return;
}
messages->MsgMsg(q.value(1)+tr(" bytes"));
QFile f(fname);
if(!f.open(QIODevice::WriteOnly))
{
messages->MsgErr(tr("cannot open file '")+fname+tr("' for writing"));
return;
}
char * pch =q.data(0);
while(*pch)
{
char byte[3]={0,0,0};
for(int x=0;x<2;x++)
{
byte[x]=*pch++;
if(!pch)
{
messages->MsgErr(tr("file '")+fname+tr("' is corrupted"));
return;
}
}
bool ok;
QString bstr(&byte[0]);
unsigned char bw=bstr.toUShort(&ok,16);
if(!ok)
{
messages->MsgErr(tr("file '")+fname+tr("' is corrupted"));
return;
}
else
f.write((const char*)&bw,1);
}
f.close();
}
ui->wdgZoomPanel->setEnabled(ui->iwImg->drawarea()->loadPage(fname,computeValue()));
}
}
void CMImages::on_btZ1_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(100);
on_sldZoom_sliderReleased();
}
void CMImages::on_btZ2_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(200);
on_sldZoom_sliderReleased();
}
void CMImages::on_btZ3_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(300);
on_sldZoom_sliderReleased();
}
void CMImages::on_btZ4_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(400);
on_sldZoom_sliderReleased();
}
/*void CMImages::checkZoomB(QToolButton * b)
{
btZ1->setChecked(false);
btZ2->setChecked(false);
btZ3->setChecked(false);
btZ4->setChecked(false);
btZD2->setChecked(false);
btZD3->setChecked(false);
btZD4->setChecked(false);
btZD5->setChecked(false);
b->setChecked(true);
}*/
void CMImages::on_btZD2_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(100/2);
on_sldZoom_sliderReleased();
}
void CMImages::on_btZD5_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(100/5);
on_sldZoom_sliderReleased();
}
void CMImages::on_btZD4_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(100/4);
on_sldZoom_sliderReleased();
}
void CMImages::on_btZD3_clicked()
{
//checkZoomB((QToolButton*)this->sender());
ui->sldZoom->setValue(100/3);
on_sldZoom_sliderReleased();
}
void CMImages::on_treeImages_customContextMenuRequested(QPoint pos)
{
QAction * a;
if((a=popup.exec(bt_action?pos:QCursor::pos())))
{
if(a==del_map)
deleteMap();
else if(a==bkp_map)
backupMap();
else if(a==reload_maps)
loadData();
else if(a==create_col)
createCollection();
else if(a==add_map)
createMap();
else if(a==edit_cm)
editItem();
else if(a==imp_img)
importImage();
else if(a==reorder_maps)
reorderMaps();
else if(a==open_map)
on_treeImages_itemDoubleClicked(ui->treeImages->currentItem(),0);
else if(a==import_col)
{
emit importRequested();
loadData();
}
else if(a==map_longlat)
setMapArea();
else if(a==expand)
ui->treeImages->expand(ui->treeImages->currentIndex());
else if(a==collapse)
ui->treeImages->collapse(ui->treeImages->currentIndex());
else if(a==expand_all)
ui->treeImages->expandAll();
else if(a==collapse_all)
ui->treeImages->collapseAll();
}
bt_action=false;
}
void CMImages::deleteMap()
{
QList<QTreeWidgetItem*> li=ui->treeImages->selectedItems();
if(!li.isEmpty())
{
//QList<QTreeWidgetItem*> cols,maps;
QString scols,smaps,qcols,qmaps;
for(int x=0;x<li.count();x++)
{
//QString s(li[x]->text(0));
if(!li[x]->parent())
{
//cols.append(li[x]);
scols.append(li[x]->text(0)+"\n");
qcols.append(li[x]->text(3)+",");
}
else
{
//maps.append(li[x]);
smaps.append(li[x]->text(0)+"\n");
qmaps.append(li[x]->text(3)+",");
}
}
if(!qcols.isEmpty())
{
qcols.chop(1);
qcols.prepend("`image_collection`.`id` in(");
qcols.append(")");
QMessageBox mb(tr("delete map"),tr("Deleting collection(s)\n\n")+scols+tr("\nContinue?"),QMessageBox::Question,QMessageBox::Cancel,QMessageBox::Yes,QMessageBox::NoButton);
if(mb.exec()==QMessageBox::Yes)
{
QString query("delete from `image_collection`,`image` using `image_collection` left join `image` on `image_collection`.`id`=`image`.`collection` where "+qcols);
MQUERY(q,query)
messages->MsgOk();
}
}
if(!qmaps.isEmpty())
{
qmaps.chop(1);
qmaps.prepend("`id` in(");
qmaps.append(")");
QMessageBox mb(tr("delete map"),tr("Deleting map(s)\n\n")+smaps+tr("\nContinue?"),QMessageBox::Question,QMessageBox::Cancel,QMessageBox::Yes,QMessageBox::NoButton);
if(mb.exec()==QMessageBox::Yes)
{
QString query("delete from `image` where "+qmaps);
MQUERY(q,query)
messages->MsgOk();
}
}
loadData();
}
else
messages->MsgWarn(tr("no item selected"));
}
void CMImages::backupMap()
{
QList<QTreeWidgetItem*> li=ui->treeImages->selectedItems();
if(!li.isEmpty())
{
QTreeWidgetItem * i=li.first();
if(i->text(2)=="collection")
{
QFileDialog fd(0,tr("backup file"),QDir::toNativeSeparators("data/backup"),"msql files (*.msql);;all files (*)");
fd.setFileMode(QFileDialog::AnyFile);
fd.setAcceptMode(QFileDialog::AcceptSave);
fd.setDefaultSuffix("msql");
if(fd.exec())
{
CProgressDialog pd;
pd.show();
QString fn(fd.selectedFiles().first());
messages->MsgMsg(tr("creating file '")+fn+"' ...");
QFile f(fn);
if(!f.open(QIODevice::WriteOnly))
{
messages->MsgErr(tr("cannot open file '")+fn+"'");
return;
}
QString query1("select `id`,quote(`name`),quote(`dirname`) from `image_collection` where `id`="+i->text(3)+" order by `id`");
QString query2("select `id`,`collection`,quote(`name`),quote(`filename`),`ord`,quote(`image`) from `image` where `collection`="+i->text(3)+" order by `ord`");
MQUERY(q1,query1)
MQUERY(q2,query2)
pd.initProgress(tr("backup ..."),q1.size()+q2.size());
while(q1.next())
{
QString line("insert into `image_collection` (`id`,`name`,`dirname`,`comment`) values (");
line.append(q1.value(0)+","+
q1.value(1)+","+
q1.value(2)+",null)"+CMySql::delimiter);
if(!f.write(line.toUtf8()))
{
messages->MsgErr(tr("cannot write into file '")+fn+"'");
f.close();
return;
}
if(pd.stopped())
{
pd.close();
messages->MsgInf(tr("interrupted"));
return;
}
pd.incProgress();
}
while(q2.next())
{
if(q2.value(5)=="NULL")
m_msg()->MsgWarn(tr("map name: '")+q2.value(2)+tr("', image is NULL, import image and backup again"));
else
{
QString line("insert into `image` (`id`,`collection`,`name`,`filename`,`ord`,`image`) values (");
line.append(q2.value(0)+","+
q2.value(1)+","+
q2.value(2)+","+
q2.value(3)+","+
q2.value(4)+","+
q2.value(5)+")"+CMySql::delimiter);
if(!f.write(line.toUtf8()))
{
messages->MsgErr(tr("cannot write into file '")+fn+"'");
f.close();
return;
}
}
if(pd.stopped())
{
pd.close();
messages->MsgMsg(tr("interrupted"));
return;
}
pd.incProgress();
}
f.close();
pd.close();
messages->MsgOk();
}
}
else
messages->MsgWarn(tr("no collection selected"));
}
else
messages->MsgWarn(tr("no collection selected"));
}
void CMImages::on_sldZoom_valueChanged(int value)
{
//spnZoom->setValue(((double)value)/100);
double v(((double)value)/100);
ui->lblValue->setText("x"+QString::number(v,'f',2));
//drawarea.scale(v);
}
void CMImages::on_sldZoom_sliderReleased()
{
double v(((double)ui->sldZoom->value())/100);
ui->iwImg->drawarea()->scale(v);
}
double CMImages::computeValue() const
{
return ((double)ui->sldZoom->value())/100;
}
void CMImages::createCollection()
{
//QString query2("select max(`id`)+1 from `image_collection`");
//MQUERY_GETFIRST(q2,query2)
//QString newid(q2.isNULL(0)?"1":q2.value(0));
QString query("insert into `image_collection` (`name`,`comment`,`dirname`) values ('New Collection','','(directory)')");
MQUERY(q,query)
messages->MsgOk();
loadData();
}
void CMImages::createMap()
{
QTreeWidgetItem * i(0);
if(ui->treeImages->selectedItems().count()>0)
i=ui->treeImages->selectedItems().first();
if(!i)
{
messages->MsgWarn(tr("no collection selected"));
return;
}
if(i->parent())
{
messages->MsgWarn(tr("no collection selected"));
return;
}
//QString query2("select max(`id`)+1 from `image`");
//MQUERY_GETFIRST(q2,query2)
//QString newid(q2.isNULL(0)?"1":q2.value(0));
QString query("insert into `image` (`collection`,`name`,`comment`,`filename`,`ord`,`image`) values ("+i->text(3)+",'new map','','(filename)',0,null)");
MQUERY(q,query)
messages->MsgOk();
loadData();
}
void CMImages::editItem()
{
QTreeWidgetItem * i(ui->treeImages->currentItem());
if(i)
{
if(!i->parent())
{
MEditImgItem d(i->text(0),i->text(1),true);
if(d.exec()==QDialog::Accepted)
{
QString query("update `image_collection` set `name`='"+d.colName()+"',`dirname`='"+d.dir()+"' where `id`="+i->text(3));
MQUERY(q,query)
m_msg()->MsgOk();
loadData();
}
}
else
{
MEditImgItem d(i->text(0),i->text(1),false);
if(d.exec()==QDialog::Accepted)
{
QString query("update `image` set `name`='"+d.bookName()+"',`filename`='"+d.file()+"' where `id`="+i->text(3));
MQUERY(q,query)
m_msg()->MsgOk();
loadData();
}
}
}
else
m_msg()->MsgWarn(tr("no item selected"));
}
void CMImages::importImage()
{
QTreeWidgetItem * i(ui->treeImages->currentItem());
if(i)
{
QTreeWidgetItem * ipar(i->parent());
if(ipar)
{
QFile f(m_sett()->marcDir+QDir::separator()+"data/maps"+QDir::separator()+ipar->text(1)+QDir::separator()+i->text(1));
QMessageBox mb(QMessageBox::Question,tr("import image"),tr("Map ")+i->text(0)+tr(" will be imported into database from file '")+f.fileName()+tr("'.\nContinue?"),QMessageBox::Ok|QMessageBox::Cancel,this);
if(mb.exec()==QMessageBox::Ok)
{
USE_CLEAN_WAIT
m_msg()->MsgMsg(tr("importing data from '")+f.fileName()+"' ...");
if(f.open(QIODevice::ReadOnly))
{
char ch;
int fo;
QByteArray imgdata;
do
{
fo=f.read(&ch,1);
if(fo==-1)
{
m_msg()->MsgErr(tr("cannot read from file '")+f.fileName()+"'");
f.close();
return;
}
QString s(QString::number(*(unsigned char*)&ch,16));
if(s.length()==1)
s.prepend("0");
if(s.length()!=2)
{
f.close();
m_msg()->MsgErr("corrupted data");
return;
}
imgdata.append(s);
}while(fo>0);
f.close();
QString query("update `image` set `image`='"+imgdata+"' where `id`="+i->text(3));
m_msg()->MsgMsg(tr("executing query ..."));
MQUERY_NOMSG(q,query)
m_msg()->MsgOk();
}
else
{
m_msg()->MsgErr(tr("cannot open file '")+f.fileName()+tr("' for reading"));
return;
}
}
}
else
m_msg()->MsgWarn(tr("no map selected"));
}
else
m_msg()->MsgWarn(tr("no item selected"));
}
void CMImages::reorderMaps()
{
QTreeWidgetItem * i(ui->treeImages->currentItem());
if(!i->parent())
{
MReorderImageItem d(i->text(3).toInt());
if(d.exec()==QDialog::Accepted)
{
for(int x=0;x<d.itemCount();x++)
{
QString query("update `image` set `ord`="+QString::number(x+1)+" where `id`="+d.itemAt(x).id);
MQUERY(q,query)
}
m_msg()->MsgOk();
loadData();
}
}
else
m_msg()->MsgWarn(tr("no collection selected"));
}
void CMImages::on_btAction_clicked()
{
bt_action=true;
on_treeImages_customContextMenuRequested(ui->btAction->mapToGlobal(QPoint()));
}
void CMImages::setMapArea()
{
QTreeWidgetItem * i(ui->treeImages->currentItem());
if(i->parent())
{
QString query("select `long`,`lat`,`tolong`,`tolat`,`x1`,`y1`,`x2`,`y2` from `image` where `id`="+i->text(3));
MQUERY_GETFIRST(q,query)
MMapLongLat d;
if(q.isNULL(0)||q.isNULL(1)||q.isNULL(2)||q.isNULL(3))
d.setNullValues();
else
d.setValues(q.value(0).toDouble(),q.value(1).toDouble(),q.value(2).toDouble(),q.value(3).toDouble());
if(q.isNULL(4)||q.isNULL(5)||q.isNULL(6)||q.isNULL(7))
d.setMapArea("null","null","null","null");
else
d.setMapArea(q.value(4),q.value(5),q.value(6),q.value(7));
d.setSelection(ui->iwImg->drawarea()->selectionRect());
if(d.exec()==QDialog::Accepted)
{
QString query2("update `image` set `long`="+d.longitude1()+",`lat`="+d.latitude1()+",`tolong`="+d.longitude2()+",`tolat`="+d.latitude2()+",`x1`="+d.x1()+",`y1`="+d.y1()+",`x2`="+d.x2()+",`y2`="+d.y2()+" where `id`="+i->text(3));
MQUERY(q2,query2)
m_msg()->MsgOk();
}
}
else
m_msg()->MsgWarn(tr("no map selected"));
}
void CMImages::on_trwLoc_customContextMenuRequested(QPoint pos)
{
}