/****************************************************************************
 **
 ** Copyright (C) 2011 Christian B. Huebschle & George M. Sheldrick
 ** All rights reserved.
 ** Contact: chuebsch@moliso.de
 **
 ** This file is part of the ShelXle
 **
 ** This file may be used under the terms of the GNU Lesser
 ** General Public License version 2.1 as published by the Free Software
 ** Foundation and appearing in the file COPYING included in the
 ** packaging of this file.  Please review the following information to
 ** ensure the GNU Lesser General Public License version 2.1 requirements
 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 **
 ****************************************************************************/
//äöüß needed to keep this file UTF8 QString::fromUtf8("»")
#include "chgl.h"
#include "deprecation.h"
//#if defined (Q_WS_MAC) || defined (Q_OS_MAC)
//#include <OpenGL/glu.h>
//#include <glu.h>
//#else
//#include <GL/glu.h>
//#endif
#include <QtGui>
#include <QtOpenGL>
#include <QDialog>
#ifndef GL_MULTISAMPLE
#define ICH_KANNTE_NICHT_MS 42
#define GL_MULTISAMPLE  0x809D
#endif
//
//#define HIDE_REASON_SELECT          1
//#define HIDE_REASON_THIS_FRAGMENT   2
//#define HIDE_REASON_OTHER_FRAGMENT  4
//#define HIDE_REASON_HYDROGEN        8
//#define HIDE_REASON_QPEAK          16 
//


inline void ChGL::__RotateCS( double c, double s, double& X, double& Y ) {
  double T = X;
  X = c*X - s*Y;
  Y = s*T + c*Y;
}

void ChGL::glTranslateL( const double dx, const double dy, const double dz ) {
  double mat[4][4];

  glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mat );
  mat[3][0] += dx;  mat[3][1] += dy;  mat[3][2] += dz;
  glLoadMatrixd((double*)mat);
}
void ChGL::glRotateL( const double dang, const double x, const double y, const double z ) {
  double mat[4][4];
#ifndef M_PI
#define	M_PI		3.14159265358979323846	/* pi */
#endif

  double s = z;
  s = sin(dang*M_PI/180);
  const double c = cos(dang*M_PI/180);
  glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mat );
  //  glGetDoublev( GL_PROJECTION_MATRIX, (double*)mat );
  if( x!=0.0 ){
    __RotateCS( c, s, mat[0][1], mat[0][2] );
    __RotateCS( c, s, mat[1][1], mat[1][2] );
    __RotateCS( c, s, mat[2][1], mat[2][2] );
    //    printf("x\n");
  }else if( y!=0.0 ){
    __RotateCS( c, s, mat[0][2], mat[0][0] );
    __RotateCS( c, s, mat[1][2], mat[1][0] );
    __RotateCS( c, s, mat[2][2], mat[2][0] );
    //    printf("y\n");
  }else{
    __RotateCS( c, s, mat[0][0], mat[0][1] );
    __RotateCS( c, s, mat[1][0], mat[1][1] );
    __RotateCS( c, s, mat[2][0], mat[2][1] );    
    //    printf("z\n");
  }
  glLoadMatrixd((double*)mat); 
}




void ChGL::saveOrientation(){
  QString fn=QFileDialog::getSaveFileName(this, tr("Save Orientation into file "), "orientation.ini",
      "orientation.ini (*.ini);;");

  if (fn.isEmpty()) return;
  QFile mconf(fn);
  mconf.open(QIODevice::WriteOnly|QIODevice::Text);
  GLdouble mm[16];
  glGetDoublev(GL_MODELVIEW_MATRIX,mm);
  mconf.write(QString("%1/%2/%3/%4/%5/%6/%7/%8/%9/%10/%11/%12/%13/%14/%15/%16\n")
      .arg(mm[0]).arg(mm[1]).arg(mm[2]).arg(mm[3]).arg( mm[4]).arg(mm[5])
      .arg(mm[6]).arg(mm[7]).arg( mm[8]).arg(mm[9]).arg(mm[10]).arg(mm[11])
      .arg( mm[12]).arg(mm[13]).arg(mm[14]).arg(mm[15]).toLatin1());
  mconf.close();
}

void ChGL::saveOrientation(QString fn){
  if (fn.isEmpty()) return;
  QFile mconf(fn);
  mconf.open(QIODevice::WriteOnly|QIODevice::Text);
  GLdouble mm[16];
  glGetDoublev(GL_MODELVIEW_MATRIX,mm);
  mconf.write(QString("%1/%2/%3/%4/%5/%6/%7/%8/%9/%10/%11/%12/%13/%14/%15/%16\n")
      .arg(mm[0]).arg(mm[1]).arg(mm[2]).arg(mm[3]).arg( mm[4]).arg(mm[5])
      .arg(mm[6]).arg(mm[7]).arg( mm[8]).arg(mm[9]).arg(mm[10]).arg(mm[11])
      .arg( mm[12]).arg(mm[13]).arg(mm[14]).arg(mm[15]).toLatin1());
  mconf.close();
}

void ChGL::rotateIdle(){
    if (idl!=NULL){                
        glRotateL(0.5,0.0,1.0,0.0);
        updateGL();
    }
}
	
void ChGL::loadOrientation(QString fn){
  if (fn.isEmpty()) return;
  QFile miconf(fn);
  miconf.open(QIODevice::ReadOnly|QIODevice::Text);
  QString all=miconf.readAll();
  miconf.close();

  MM[0] = all.section('/',0,0).toDouble();
  MM[1] = all.section('/',1,1).toDouble(); 
  MM[2] = all.section('/',2,2).toDouble();
  MM[3] = all.section('/',3,3).toDouble();
  MM[4] = all.section('/',4,4).toDouble();
  MM[5] = all.section('/',5,5).toDouble();
  MM[6] = all.section('/',6,6).toDouble();
  MM[7] = all.section('/',7,7).toDouble();
  MM[8] = all.section('/',8,8).toDouble();
  MM[9] = all.section('/',9,9).toDouble();
  MM[10]= all.section('/',10,10).toDouble();
  MM[11]= all.section('/',11,11).toDouble();
  MM[12]= all.section('/',12,12).toDouble();
  MM[13]= all.section('/',13,13).toDouble();
  MM[14]= all.section('/',14,14).toDouble();
  MM[15]= all.section('/',15,15).toDouble();
  printf("matrix:\n%12g %12g %12g %12g\n%12g %12g %12g %12g\n%12g %12g %12g %12g\n%12g %12g %12g %12g\n",
      MM[0], 
      MM[1] ,
      MM[2] ,
      MM[3] ,
      MM[4] ,
      MM[5] ,
      MM[6] ,
      MM[7] ,
      MM[8] ,
      MM[9] ,
      MM[10],
      MM[11],
      MM[12],
      MM[13],
      MM[14],
      MM[15]);
  setMatrix();
  //  emit mconf();
  updateGL();
}

void ChGL::loadOrientation(){
  QString fn=QFileDialog::getOpenFileName(this, tr("Open MoleCoolQt MolIso Settings file "), "MoleCoolQt.moliso.ini",
      "MoleCoolQt.moliso.ini (*.ini);;" );

  if (fn.isEmpty()) return;
  QFile miconf(fn);
  miconf.open(QIODevice::ReadOnly|QIODevice::Text);
  QString all=miconf.readAll();
  miconf.close();

  MM[0] = all.section('/',0,0).toDouble();
  MM[1] = all.section('/',1,1).toDouble(); 
  MM[2] = all.section('/',2,2).toDouble();
  MM[3] = all.section('/',3,3).toDouble();
  MM[4] = all.section('/',4,4).toDouble();
  MM[5] = all.section('/',5,5).toDouble();
  MM[6] = all.section('/',6,6).toDouble();
  MM[7] = all.section('/',7,7).toDouble();
  MM[8] = all.section('/',8,8).toDouble();
  MM[9] = all.section('/',9,9).toDouble();
  MM[10]= all.section('/',10,10).toDouble();
  MM[11]= all.section('/',11,11).toDouble();
  MM[12]= all.section('/',12,12).toDouble();
  MM[13]= all.section('/',13,13).toDouble();
  MM[14]= all.section('/',14,14).toDouble();
  MM[15]= all.section('/',15,15).toDouble();
  printf("matrix:\n%12g %12g %12g %12g\n%12g %12g %12g %12g\n%12g %12g %12g %12g\n%12g %12g %12g %12g\n",
      MM[0], 
      MM[1] ,
      MM[2] ,
      MM[3] ,
      MM[4] ,
      MM[5] ,
      MM[6] ,
      MM[7] ,
      MM[8] ,
      MM[9] ,
      MM[10],
      MM[11],
      MM[12],
      MM[13],
      MM[14],
      MM[15]);
  setMatrix();
  //  emit mconf();
  updateGL();
}

void ChGL::setMatrix(){
  glMatrixMode(GL_MODELVIEW);
  GLdouble det=
    MM[0]*MM[5]*MM[10] - MM[8]*MM[5]*MM[2]+
    MM[1]*MM[6]*MM[8]  - MM[9]*MM[6]*MM[0]+
    MM[2]*MM[4]*MM[9]  - MM[10]*MM[4]*MM[1];
  //printf("Determinant is %g\n",det);
  //if ((det>0.1)&&(det<9.0)) 
  glLoadMatrixd(MM);
  /*else {
    MM[0]=1;
    MM[1]=0;
    MM[2]=0;
    MM[3]=0;
    MM[4]=0;
    MM[5]=1;
    MM[6]=0;
    MM[7]=0;
    MM[8]=0;
    MM[9]=0;
    MM[10]=1;
    MM[11]=0;
    MM[12]=0;
    MM[13]=0;
    MM[14]=-200;
    MM[15]=1;
    glLoadIdentity();
    glLoadMatrixd(MM);
    }*/
  updateGL();
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ChGL::ChGL(QWidget *parent) : QGLWidget(QGLFormat(QGL::SampleBuffers),parent){                                                        ///////////////
ChGL::ChGL(QWidget *parent) :QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::DeprecatedFunctions),parent){
  //printf("ChGL::ChGL\n");|QGL::DoubleBuffer|QGL::DepthBuffer|QGL::DirectRendering|QGL::StereoBuffers
  QGLFormat glf=format();
  printf("sampleBuffers=%d alpha=%d doubleBuffer=%d depth=%d directRendering=%d stereo=%d hasOverlay=%d stencil=%d samples=%d sync?%d\n"
      ,glf.sampleBuffers(), glf.alpha(), glf.doubleBuffer(), glf.depth(), glf.directRendering(), glf.stereo(),glf.hasOverlay(),glf.stencil (),glf.samples(),glf.swapInterval());
#ifdef ICH_KANNTE_NICHT_MS
  printf("msaa ndef %d\n",ICH_KANNTE_NICHT_MS);
#endif
  inRenameMode=false;
  fVertexes.resize(28);
  fNormals.resize(28);
  pause=true;
  depthcueing=false;
  retinafktr=1;
  on=false;
  idl=NULL;
  //orthoView=false;
  withsymm=0;
  labScal=0.3;
  exporting=false;
  dratpause=80;
  murx=0;
  chparent=parent;
  envirange=3.2;
  apair.clear();
  enviNoQ= new QAction("Exclude Q-peaks from environment listing", this);
  enviCova = new QAction("List only covalent bonds.",this);
  enviButt= new QToolButton(this);
  enviButt->setText("clear ENVI");
  connect(enviButt,SIGNAL(clicked()),this,SLOT(clearEnvi()));
  enviSelect= new QToolButton(this);
  enviSelect->setText("Select ENVI");
  connect(enviSelect,SIGNAL(clicked()),this,SLOT(selectEnvi()));
  wireButt= new QAction("Wiremodel while rotate",this);
  wireButt->setCheckable(true);
  wireButt->setChecked(false);//defaut changed 13.12.2019
  rainbowPlot= new QAction("Contour plot in rainbow colors",this);
  rainbowPlot->setCheckable(true);
  rainbowPlot->setChecked(false);
  rainbowPlot->setVisible(false);
  enviButt->setVisible(false);
  enviSelect->setVisible(false);
  enviNoQ->setCheckable(true);
  enviNoQ->setChecked(false);
  enviCova->setCheckable(true);
  enviCova->setChecked(false);
  mol=new Molecule();
  warLabel=noWaitLabel=false;
  viewAngle=29.0;
  imFokus=afok=-1;
  pickradius=200.0;
  //printf("__ChGL::ChGL\n");
  moving = new QTimer(this);
  moving->setSingleShot(true);
  connect(moving,SIGNAL(timeout()),this,SLOT(updateGL()));
  p=pp=ppp=0;
  bggradient=true;
  altemitte=V3(0,0,0);
  hiddenThings=false;
  hideReason=0;
  qcutoff=-9;
  setMinimumSize(200,200);
  myFont=QFont("Arial",16);
  centerSelection = new QAction(this);//for a dirty fix
  rotze=-1;                                                                                              ///////////////
  stereo_mode=0;                                                                                         ///////////////a
  atomsClickable=true;                                                                                   ///////////////
  mouseOverInteraction=true;                                                                             ///////////////
  //  warfaul=
  drawUc=false;

  // 0  1  2  3
  // 4  5  6  7
  // 8  9 10 11
  //12 13 14 15
  MM[0]=-1;
  MM[1]=MM[2]=MM[3]=MM[4]=MM[7]=MM[8]=MM[11]=MM[12]=MM[13]=0;
  MM[5]=-0.242536;
  MM[6]=0.970142;
  MM[9]=0.970142;
  MM[10]=0.242536;
  MM[15]=1.0;
  //MM[1]=MM[2]=MM[3]=MM[4]=MM[6]=MM[7]=MM[8]=MM[9]=MM[11]=MM[12]=MM[13]=0.0;
  MM[14]=-200.0;
  drawDF=drawFO= drawAx=drawAt=drawADP=drawBo=drawLa=drawHb=true;
  //glEnable(GL_MULTISAMPLE);
  ///////////////
#if (QT_VERSION >= 0x040600) && defined (Q_WS_MAC)
  grabGesture(Qt::PinchGesture);
  grabGesture(Qt::SwipeGesture);
#endif
  /*
     QGLFormat fmt=QGLFormat::defaultFormat() ;
  //fmt.setOption(QGL::StereoBuffers);
  fmt.setOption(QGL::DirectRendering|QGL::StereoBuffers);
  //fmt.setOption(QGL::);
  setFormat(fmt);
  */
  //                                                                                                     ///////////////
}                                                                                                        ///////////////

ChGL::~ChGL(){
  if (mol->g_Program!=NULL) mol->g_Program->deleteLater();
  labelTextures.clear();  
  //printf("Destructor of chGL %d %d\n",fVertexes.size(),fNormals.size());
  int sumsize=0;
  for (int i=0; i<fVertexes.size(); i++) {sumsize+=fVertexes[i].size(); fVertexes[i].clear();}
  for (int i=0; i<fNormals.size(); i++) {sumsize+=fNormals[i].size(); fNormals[i].clear();}
  fVertexes.clear();
  fNormals.clear();
  //printf("Destructor of chGL freed %d normals and vertices.\n",sumsize);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#if (QT_VERSION >= 0x040600) && (defined (Q_WS_MAC) || defined(Q_OS_MAC))
bool ChGL::event(QEvent *event){
  if (event->type() == QEvent::Gesture)
    return gestureEvent(static_cast<QGestureEvent*>(event));
  return QWidget::event(event);
}

bool ChGL::gestureEvent(QGestureEvent *event){
  if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
    swipeTriggered(static_cast<QSwipeGesture *>(swipe));
  else
    if (QGesture *pinch = event->gesture(Qt::PinchGesture))
      pinchTriggered(static_cast<QPinchGesture *>(pinch));
  return true;
}

void ChGL::pinchTriggered(QPinchGesture *gesture){
  QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
  if (changeFlags & QPinchGesture::RotationAngleChanged) {
    qreal value = gesture->property("rotationAngle").toReal();
    rotZ(value/-36.0);
  }
  if (changeFlags & QPinchGesture::ScaleFactorChanged) {
    qreal value = gesture->property("scaleFactor").toReal();
    gZoom(value-1.0);
  }
  updateGL();
}

void ChGL::swipeTriggered(QSwipeGesture *gesture) {
  if (gesture->horizontalDirection() == QSwipeGesture::Left) glRotateL(-5.0,0.0f,1.0f,0.0f);
  if (gesture->horizontalDirection() == QSwipeGesture::Right) glRotateL(5.0,0.0f,1.0f,0.0f);
  if (gesture->verticalDirection() == QSwipeGesture::Up) glRotateL(-5.0,1.0f,0.0f,0.0f);
  if (gesture->verticalDirection() == QSwipeGesture::Down) glRotateL(5.0,1.0f,0.0f,0.0f);
  updateGL();
}
#endif



static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4]) {
#define M(row,col)  m[col*4+row]
  out[0] =
    M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
  out[1] =
    M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
  out[2] =
    M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
  out[3] =
    M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}
int scrx=0,scry=0;
int scrx0=0,scry0=0;
bool rectangle=false;
static inline bool  posTo2D(V3 obj,
    const GLdouble model[16], const GLdouble proj[16],
    const GLint viewport[4],
    GLdouble * winx, GLdouble * winy,int retinafktr) {
  GLdouble in[4], out[4];

  in[0] = obj.x;
  in[1] = obj.y;
  in[2] = obj.z;
  in[3] = 1.0;
  transform_point(out, model, in);
  transform_point(in, proj, out);

  if (in[3] == 0.0) return false;

  in[0] /= in[3];
  in[1] /= in[3];
  in[2] /= in[3];

  *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
  *winy = viewport[1] + (1 - in[1]) * viewport[3] / 2;
  *winx/=retinafktr;
  *winy/=retinafktr;
  return true;

}


void ChGL::changeEnviRange(){//! a dialog for a new ChGL.envirange.
  bool ok;
  double r=QInputDialog::getDouble ( this,"Envi-Range", "change environment range", envirange,0.7,8.0,2,&ok);
  if (ok) envirange=r;
}

void ChGL::mousePressEvent(QMouseEvent *event) {
  if (rectangle){
    rectangle=false;
    updateGL();
  }
  lastPos = event->pos();
  p = qMin(p,mol->showatoms.size()-1);
  pp = qMin(pp,mol->showatoms.size()-1);
  ppp = qMin(ppp,mol->showatoms.size()-1);

  p = qMax(p,0);
  pp = qMax(pp,0);
  ppp = qMax(ppp,0);
  double nahda=pickradius,da=0;
  int nahdai=-1;
  for (int j=0; j<mol->showatoms.size();j++){
    if (mol->showatoms.at(j).hidden) continue;
    da=(((mol->showatoms.at(j).screenX-event->x())*( mol->showatoms.at(j).screenX-event->x()))+
        ((mol->showatoms.at(j).screenY-event->y())*( mol->showatoms.at(j).screenY-event->y())));
    nahdai=(da<nahda)?j:nahdai;
    nahda=qMin(nahda,da);
  }
  //  printf("press =>%d RNM%d %d\n",nahdai,inRenameMode,mol->selectedatoms.size());
  //if (nahdai!=-1)printf("MousePressEvent %d %d %f\n",nahdai,mol->showatoms.size(),nahda);
  //  fprintf(stderr,"pressed %d %d %d  %d\n",p,pp,ppp,mol->showatoms.size());
  if (event->buttons() & Qt::MidButton){

    if (nahdai < 0) {
    }else 
      if (nahdai<mol->showatoms.size()) {
        int index=nahdai;
        if (index==(-1))return;
        rotze=((int)index<mol->showatoms.size())?index:-1;
        if (rotze>-1){ rCenter->show();

          glGetDoublev(GL_MODELVIEW_MATRIX,MM);
          MM[12]=MM[13]=0;
          glLoadMatrixd(MM);
        }
        updateGL();

      }
  }
  //*/
  //  if((reSe | moveLab| invEditAble | atomsClickable| xdSetupMode) && 
  if (event->buttons() & Qt::LeftButton){
    scrx0=lastPos.x();
    scry0=lastPos.y();
    if (nahdai < 0) {
    }else 
      if (nahdai<mol->showatoms.size()) {
        int index=nahdai;
        if (index==(-1))return;
        double w=0,dw=0;
        if ((pp!=p)&&(pp!=index)&&(p!=index)) {
          V3 aa1=mol->showatoms.at(p).pos-mol->showatoms.at(pp).pos;
          V3 aa2=mol->showatoms.at(p).pos-mol->showatoms.at(index).pos;
          w=mol->winkel(aa1,aa2);
          if ((ppp!=p)&&(ppp!=pp)&&(ppp!=index))
            dw=mol->dieder(mol->showatoms.at(pp).pos-mol->showatoms.at(ppp).pos,
                mol->showatoms.at(pp).pos-mol->showatoms.at(p).pos,
                mol->showatoms.at(p).pos-mol->showatoms.at(index).pos);
        }
        if (atomsClickable){
          emit jumpit(index);
         /* printf("%s %d %d\n",
              mol->showatoms.at(index).Label.toStdString().c_str(),
              mol->showatoms.at(index).scod,
              mol->showatoms.at(index).an);*/
          if (inRenameMode) return;
          if (!inRenameMode){              
            apair.clear();
            if (event->modifiers()==Qt::NoModifier) {
              int isschon=-1;
              for (int i=0; i< mol->selectedatoms.size();i++){
                isschon=(mol->selectedatoms.at(i).style==index)?index:isschon;
              }
              mol->selectedatoms.clear();
              if (isschon==-1){
                mol->selectedatoms.append(mol->showatoms[index]);
                mol->selectedatoms.last().style=index;
              }
            }
            if (event->modifiers()==Qt::ShiftModifier) {
              int min=mol->showatoms.size(), max=-1;
              for (int i=0; i< mol->selectedatoms.size();i++){
                min=qMin(mol->selectedatoms.at(i).style,min);
                max=qMax(mol->selectedatoms.at(i).style,max);
              }
              min=qMin((int)index,min);
              max=qMax((int)index,max);
              mol->selectedatoms.clear();
              for (int i=min; i<=max; i++){
                mol->selectedatoms.append(mol->showatoms[i]);
                mol->selectedatoms.last().style=i;
              }
            }
            if (event->modifiers()==Qt::ControlModifier) {
              if (mol->selectedatoms.contains(mol->showatoms[index])){
                mol->selectedatoms.removeOne(mol->showatoms[index]);
              } else {
                mol->selectedatoms.append(mol->showatoms[index]);
                mol->selectedatoms.last().style=index;
                //                for (int oo=0; oo<mol->selectedatoms.size(); oo++) qDebug()<<mol->selectedatoms.at(oo).Label<<mol->selectedatoms.at(oo).symmGroup<< mol->selectedatoms.at(oo).style<<mol->selectedatoms.size();
              }
            }
            //	  std::cout<<mol->selectedatoms.size()<<mol->selectedatoms.last().Label.toStdString()<<std::endl;
            emit selectionChanged();
            updateBondActions();
            updateGL();
          }
          //

          V3 hin;
          double dmsda=0;
          hin = Normalize(mol->showatoms.at(index).pos-mol->showatoms.at(p).pos);
          if ((mol->showatoms.at(index).an>-1) && (mol->showatoms.at(p).an)) 
            dmsda = fabs(((hin*mol->showatoms.at(index).uc)*hin)- ((hin*mol->showatoms.at(p).uc)*hin)); 
          //
          bool syok;
          QString symml;
          int syid=mol->showatoms.at(index).Label.section(QString::fromUtf8("»"),1).toInt(&syok);
          if (mol->usedSymmetry.size()&&syok) symml=mol->symmcode2human(mol->usedSymmetry.at(syid-1),syid);
          syid=mol->showatoms.at(p).Label.section(QString::fromUtf8("»"),1).toInt(&syok);
          if ((mol->usedSymmetry.size())&&(syok)&&(!symml.contains(mol->symmcode2human(mol->usedSymmetry.at(syid-1),syid)))) 
            symml+=mol->symmcode2human(mol->usedSymmetry.at(syid-1),syid);

          syid=mol->showatoms.at(pp).Label.section(QString::fromUtf8("»"),1).toInt(&syok);
          if ((mol->usedSymmetry.size())&&(syok)&&(!symml.contains(mol->symmcode2human(mol->usedSymmetry.at(syid-1),syid)))) 
            symml+=mol->symmcode2human(mol->usedSymmetry.at(syid-1),syid);

          syid=mol->showatoms.at(ppp).Label.section(QString::fromUtf8("»"),1).toInt(&syok);
          if ((mol->usedSymmetry.size())&&(syok)&&(!symml.contains(mol->symmcode2human(mol->usedSymmetry.at(syid-1),syid)))) 
            symml+=mol->symmcode2human(mol->usedSymmetry.at(syid-1),syid);
          /*printf("%s org=%s iso=%d\n a%9.6f b%9.6f c%9.6f  %9.6f %9.6f %9.6f\n d%9.6f e%9.6f f%9.6f  %9.6f %9.6f %9.6f\n g%9.6f h%9.6f i%9.6f  %9.6f %9.6f %9.6f\n\n",
            mol->showatoms.at(index).Label.toStdString().c_str(),
            mol->showatoms.at(index).ufiso_org.toStdString().c_str(),
            mol->showatoms.at(index).isIso,
            mol->showatoms.at(index).uf.m11,mol->showatoms.at(index).uf.m12,mol->showatoms.at(index).uf.m13,  mol->showatoms.at(index).uc.m11,mol->showatoms.at(index).uc.m12,mol->showatoms.at(index).uc.m13,
            mol->showatoms.at(index).uf.m21,mol->showatoms.at(index).uf.m22,mol->showatoms.at(index).uf.m23,  mol->showatoms.at(index).uc.m21,mol->showatoms.at(index).uc.m22,mol->showatoms.at(index).uc.m23,
            mol->showatoms.at(index).uf.m31,mol->showatoms.at(index).uf.m32,mol->showatoms.at(index).uf.m33,  mol->showatoms.at(index).uc.m31,mol->showatoms.at(index).uc.m32,mol->showatoms.at(index).uc.m33
            );// */

          if ((index!=p)&&(index!=pp)&&(mol->showatoms.at(index).Label[0]=='Q')){
            /*printf("scod %d %f %f %f \n",mol->showatoms.at(index).scod,
              mol->showatoms.at(index).frac.x,
              mol->showatoms.at(index).frac.y,
              mol->showatoms.at(index).frac.z);//  **/
            emit bigmessage(QString("<hr><table><tr><td><b>%1</b></td><td align=\"right\"></td></tr><tr><td><b>%1--%2</b>"
                  "</td><td align=\"right\">%5 &Aring;</td></tr><tr><td><b>%1--%2--%3</b></td><td "
                  "align=\"right\">%6&deg;</td></tr><tr><td><b>%1--%2--%3--%4 </b></td><td "
                  "align=\"right\">%7&deg;</td></tr><tr><td><b>%1</b> Peak Height: </td><td "
                  "align=\"right\">%8 e&Aring;<sup>-3</sup></td><td>[%9&hellip;%10]"
                  "</td></tr></table>%11")
                .arg((mol->showatoms.at(index).Label))                     //1
                .arg((mol->showatoms.at(p).Label))				//3
                .arg((mol->showatoms.at(pp).Label))			                //5			                                                //8
                .arg((mol->showatoms.at(ppp).Label))			                        //9
                .arg(sqrt(Distance(mol->showatoms.at(index).pos,mol->showatoms.at(p).pos)),8,'f',3) //4
                .arg(w,8,'f',2)
                .arg(dw,8,'f',2)
                .arg(mol->showatoms.at(index).peakHeight,8,'f',2)
                .arg(mol->pmin,3,'f',2)
                .arg(mol->pmax,3,'f',2)
                .arg(symml)

                );
          }
          else if ((index!=p)&&(index!=pp)&&(mol->showatoms.at(index).Label[0]=='L')&&(mol->showatoms.at(index).an==-42)){
            emit bigmessage(QString("<hr><table><tr><td><b>%1</b></td><td align=\"right\"></td></tr><tr><td><b>%1--%2</b>"
                  "</td><td align=\"right\">%5 &Aring;</td></tr><tr><td><b>%1--%2--%3</b></td><td "
                  "align=\"right\">%6&deg;</td></tr><tr><td><b>%1--%2--%3--%4 </b></td><td "
                  "align=\"right\">%7&deg;</td></tr><tr><td><b>%1</b> a exp(-b x<sup>2</sup>)</td><td "
                  "align=\"right\">a = %8 </td><td> b = %9 "
                  "</td></tr></table>%11")
                .arg((mol->showatoms.at(index).Label))                     //1
                .arg((mol->showatoms.at(p).Label))				//3
                .arg((mol->showatoms.at(pp).Label))			                //5			                                                //8
                .arg((mol->showatoms.at(ppp).Label))			                        //9
                .arg(sqrt(Distance(mol->showatoms.at(index).pos,mol->showatoms.at(p).pos)),8,'f',3) //4
                .arg(w,8,'f',2)
                .arg(dw,8,'f',2)
                .arg(mol->showatoms.at(index).sof,8,'f',2)
                .arg(mol->showatoms.at(index).peakHeight,8,'f',2)
                .arg(symml)

                );
          }
          else if ((index!=p)&&(index!=pp)){
            emit bigmessage(QString("<br><hr><table><tr><td><b>%1</b> part: %8 residue: %9 %10 (fragment: %12)</td><td align=\"right\">"
                  "</td></tr><tr><td><b>%1--%2</b></td><td align=\"right\">%5 &Aring;</td><td>&nbsp;&nbsp;&nbsp;DMSDA: %13 &Aring;<sup>2</sup></td></tr>"
                  "<tr><td><b>%1--%2--%3</b></td><td align=\"right\">%6&deg;</td><td>&nbsp;&nbsp;&nbsp;1,3 Distance( DANG) %14 &Aring;</td></tr><tr><td>"
                  "<b>%1--%2--%3--%4 </b></td><td align=\"right\">%7&deg;</td></tr></table>%11")
                .arg((mol->showatoms.at(index).Label))			       //1
                .arg((mol->showatoms.at(p).Label))			               //2
                .arg((mol->showatoms.at(pp).Label))			       //3
                .arg((mol->showatoms.at(ppp).Label))			       //4
                .arg(sqrt(Distance(mol->showatoms.at(index).pos,mol->showatoms.at(p).pos)),8,'f',3) //5
                .arg(w,8,'f',2)			                            //6
                .arg(dw,8,'f',2)                                               //7
                .arg(mol->showatoms.at(index).part)
                .arg(mol->showatoms.at(index).resiNr)
                .arg(mol->showatoms.at(index).ResiClass)
                .arg(symml)
                .arg(mol->showatoms.at(index).molindex)
                .arg(dmsda,5,'e',2)
                .arg(sqrt(Distance(mol->showatoms.at(index).pos,mol->showatoms.at(pp).pos)),8,'f',3) 
                );
          }
          //				   ,QMessageBox::Ok);
          ppp = pp;
          pp = p;
          p = index;
        }

        //888
      }
  }
}

void ChGL::mouseMoveEvent(QMouseEvent *event) {
  double nahda=pickradius,da=0;
  rectangle=false;
  int nahdai=-1;
  bool changed=false;
  scrx=event->x();
  scry=event->y();
  for (int j=0; j<mol->showatoms.size();j++){
    if (mol->showatoms.at(j).hidden) continue;
    da=(((mol->showatoms.at(j).screenX-event->x())*( mol->showatoms.at(j).screenX-event->x()))+ 
        ((mol->showatoms.at(j).screenY-event->y())*( mol->showatoms.at(j).screenY-event->y())));
    nahdai=(da<nahda)?j:nahdai;
    nahda=qMin(nahda,da);
  }
  //if (nahdai!=-1)printf("MouseMoveEvent %d %d %f\n",nahdai,mol->showatoms.size(),nahda);
  // printf("move =>%d\n",nahdai);
  if ((mouseOverInteraction)&&(!event->buttons())) {
    if (imFokus!=nahdai) changed=true;
    imFokus=nahdai;
    if (imFokus==-1) {
      emit qpfoci(-1.0);
      emit message("");
    }
    else {
      emit message(mol->showatoms.at(imFokus).Label);
      if ((mol->showatoms.at(imFokus).an<0)) emit qpfoci(mol->showatoms.at(imFokus).peakHeight);
      else qpfoci(-1.0);
    }

    if (changed) {
      // printf("MouseMoveEvent changed %d %d %d\n",nahdai,mol->showatoms.size(),imFokus);fflush(stdout);
      updateGL();
    }
    return;
  }
  GLfloat dx = GLfloat( event->x() - lastPos.x()) / ww;
  GLfloat dy = GLfloat( event->y() - lastPos.y()) / wh;

  if (event->buttons() & Qt::MidButton){

    moving->start(dratpause);
    glTranslateL(dx*viewAngle*3,-dy*viewAngle*3,0);
    updateGL();
  }

  if ((event->buttons() & Qt::LeftButton && (event->modifiers()==(Qt::ShiftModifier|Qt::ControlModifier)))) {
    rectangle=true;
    int minxp=ww,minyp=wh,maxxp=0,maxyp=0;
    minxp=qMin(scrx0,scrx);
    minyp=qMin(scry0,scry);
    maxxp=qMax(scrx0,scrx);
    maxyp=qMax(scry0,scry);
    mol->selectedatoms.clear();
    for (int j=0; j<mol->showatoms.size();j++){
      if (mol->showatoms.at(j).hidden) continue;
      if ((mol->showatoms.at(j).screenX>minxp)&&
          (mol->showatoms.at(j).screenX<maxxp)&&
          (mol->showatoms.at(j).screenY>minyp)&&
          (mol->showatoms.at(j).screenY<maxyp)){

        mol->selectedatoms.append(mol->showatoms[j]);
        mol->selectedatoms.last().style=j;
      }
    }
    updateBondActions();
    updateGL();
  }else
    if ((event->buttons() & Qt::LeftButton)) {
      if (event->modifiers()==Qt::ShiftModifier) {
        moving->start(dratpause);
        glTranslateL(dx*viewAngle*3,-dy*viewAngle*3,0);
        updateGL();}
      else
      {
        moving->start(dratpause);
        double slow=1.0;
        if (event->modifiers()==Qt::ShiftModifier) slow=0.25;
        if (event->modifiers()==Qt::ControlModifier) slow=0.06;
        emit movedByUser();
        //if ((idl!=NULL)&&(idl->isActive())) idl->stop();
        glRotateL(dy*360.0*slow,1.0f,0.0f,0.0f);
        glRotateL(dx*360.0*slow,0.0f,1.0f,0.0f);
      }
      updateGL();
    }
    else if((event->buttons() & Qt::RightButton)){
      if (!invertMouseZoom->isChecked()){

        moving->start(dratpause);
        glScaled(1.0-dy,1.0-dy,1.0-dy);
        //     mlsc/=1.0-dy;
      }else {

        moving->start(dratpause);
        glScaled(1.0+dy,1.0+dy,1.0+dy);
        //     mlsc/=1.0+dy;
      }
      updateGL();
    }
  lastPos = event->pos();
}

QList<int> ChGL::lastClicked(){
  QList<int> pppp;
  //if ((ppp>=0)&&(ppp<mol->showatoms.size())&&(ppp!=pp)&&(ppp!=p)) pppp.append(ppp);
  if ((  p>=0)&&(  p<mol->showatoms.size())) pppp.append(p);
  if (( pp>=0)&&( pp<mol->showatoms.size())&&(pp!=p)) pppp.append(pp);
  return pppp;
}

void ChGL::wheelEvent(QWheelEvent *event){
  /*
modifiers:
Qt::NoModifier	        0x00000000	No modifier key is pressed.
Qt::ShiftModifier	    0x02000000	A Shift key on the keyboard is pressed.
Qt::ControlModifier	    0x04000000	A Ctrl key on the keyboard is pressed.
Qt::AltModifier	        0x08000000	An Alt key on the keyboard is pressed.
Qt::MetaModifier	    0x10000000	A Meta key on the keyboard is pressed.
Qt::KeypadModifier	    0x20000000	A keypad button is pressed.
Qt::GroupSwitchModifier	0x40000000	X11 only. A Mode_switch key on the keyboard is pressed.
*/ 
  int numDegrees = event->delta() / 8;
  int numSteps = numDegrees / 15;
  if (event->modifiers()==Qt::NoModifier){
    int d = myFont.pointSize();
    d=(d+numSteps>4)?d+numSteps:d;
    labScal+=0.01*numSteps;
    labScal=(labScal<0.1)?0.1:labScal;
    d=qMax(d,7);
    if (!useTextureLabels->isChecked()) myFont.setPointSize(d);
    updateGL();
  }
  if (event->modifiers()==Qt::ControlModifier){
    emit diffscroll(numSteps,1); 
  } 
  if (event->modifiers()==Qt::ShiftModifier){
    emit diffscroll(numSteps,0); 
  }
  if (event->modifiers()==(Qt::AltModifier|Qt::ShiftModifier)){
    double va=viewAngle+0.1*numSteps;
    setViewAngle(va);
  }
  if (event->modifiers()==Qt::AltModifier){
    int afr=mol->fogrange;
    mol->fogrange+=numSteps*5;
    mol->fogrange=qMax(mol->fogrange,1);
    mol->fogrange=qMin(mol->fogrange,204);
    //printf("fogrange = %d\n", mol->fogrange);
    if (afr!=mol->fogrange){
      glFogi(GL_FOG_MODE,GL_LINEAR);
      glFogi(GL_FOG_START,205-mol->fogrange);
      glFogi(GL_FOG_END,205+mol->fogrange);
      GLfloat fgc[4]={(GLfloat)backGroundColor.redF(),(GLfloat)backGroundColor.greenF(),(GLfloat)backGroundColor.blueF(),1.0};
      glFogfv(GL_FOG_COLOR,fgc);
      updateGL();}
  }

  event->accept();
}

void ChGL::contextMenuEvent(QContextMenuEvent *event){
  double nahda=pickradius,da=0;
  int nahdai=-1;
  for (int j=0; j<mol->showatoms.size();j++){
    if (mol->showatoms.at(j).hidden) continue;
    da=(((mol->showatoms.at(j).screenX-event->x())*( mol->showatoms.at(j).screenX-event->x()))+
        ((mol->showatoms.at(j).screenY-event->y())*( mol->showatoms.at(j).screenY-event->y())));
    nahdai=(da<nahda)?j:nahdai;
    nahda=qMin(nahda,da);
  }

  //printf("contextEvent %d %d %f\n",nahdai,mol->showatoms.size(),nahda);
  if ((nahdai < 0)||(mol->showatoms.size()<nahdai)) {
    return;
  }
  else {
    int idx=nahdai;
    ImeanThisAtom=idx;
    if (idx>mol->showatoms.size()) return;
    QList<QAction *> sfas = sfacMenu->actions();
    for (int k=0;k<sfas.size();k++){
      sfas[k]->setEnabled(sfas[k]->text()!=mol->pse(mol->showatoms.at(idx).an));
    }
    QMenu *menu = new QMenu(mol->showatoms.at(idx).Label);
    if (mol->showatoms.at(idx).symmGroup==0) menu->addMenu(sfacMenu);
    QAction *a;
    if ((mol->selectedatoms.isEmpty())&&(mol->showatoms.at(idx).symmGroup==0)) {
      a=menu->addAction(QIcon(":/xle-icons/killselected.svg"),QString("Delete %1 ").arg(mol->showatoms.at(idx).Label),
          chparent,SLOT(deleteSelectedAtoms()));
      a->setData(idx);
    }else if (mol->showatoms.at(idx).symmGroup==0){
      a=menu->addAction(QIcon(":/xle-icons/killselected.svg"),QString("Delete selected atoms"),
          chparent,SLOT(deleteSelectedAtoms()));
      a->setData(-1);
    }
    if (!mol->selectedatoms.isEmpty()) a=menu->addAction("Change RESI or PART of selected atoms",chparent,SLOT(changeResiPart()));
    menu->addSeparator();
    a=menu->addAction(QString("Set rotation center to %1").arg(mol->showatoms.at(idx).Label),this,SLOT(setRotationCenter()));
    a->setData(idx);
    a=menu->addAction(QString("Expand contacts around %1").arg(mol->showatoms.at(idx).Label),this,SLOT(expand()));
    a->setData(idx);
    a=menu->addAction(QString("Hide this fragment"),this,SLOT(hideThisFragment()));
    a->setData(idx);
    a=menu->addAction(QString("Select this fragment"),this,SLOT(selectThisFragment()));
    a->setData(idx);
    a=menu->addAction(QString("Hide other fragments"),this,SLOT(hideOtherFragments()));
    a->setData(idx);
    a=menu->addAction(QString("Fragment includes symmetry generated"), this ,SLOT(toogleWithSymmetry(bool)));
    a->setCheckable(true);
    a->setChecked(!(withsymm));
    if (!mol->selectedatoms.isEmpty()) a=menu->addAction("Hide selected Atoms",this,SLOT(hideSelected()));
    bool hasSameBonds=false;//for sadi two neighbor) atoms need to be same atomic number and no hydrogen
    //it warks if they are not the same but gives a warning and does not make much sense
    if (idx<mol->asymm.size()) for (int nb=1; nb<mol->knoepfe.at(idx).neighbors.size(); nb++){
      if ((mol->knoepfe.at(idx).neighbors.at(nb-1)>=mol->asymm.size())||(mol->knoepfe.at(idx).neighbors.at(nb)>=mol->asymm.size())) continue;
      if ((mol->asymm.at(mol->knoepfe.at(idx).neighbors.at(nb-1)).an>0)&&
          (mol->asymm.at(mol->knoepfe.at(idx).neighbors.at(nb-1)).an==mol->asymm.at(mol->knoepfe.at(idx).neighbors.at(nb)).an))hasSameBonds=true;
    }
    //  qDebug()<<hasSameBonds;
    if(!mol->selectedatoms.isEmpty()){
      QMenu *RestrMenu = new QMenu("Add restraints");
      QMenu *ConstrMenu = new QMenu("Add constraints");
      RestrMenu->addAction("ISOR", this, SLOT(addISOR()));
      if (hasSameBonds){
        QAction *restr;
        restr=RestrMenu->addAction("SADI", this, SLOT(addSADI()));
        restr->setData(idx);
      }
      if(mol->selectedatoms.size() == 2){
        RestrMenu->addAction("DFIX", this, SLOT(addDFIX()));
        RestrMenu->addAction("DANG", this, SLOT(addDANG()));
      }
      if(mol->selectedatoms.size() >= 4){
        RestrMenu->addAction("FLAT", this, SLOT(addFLAT()));
      }
      if(mol->selectedatoms.size() > 1){
        ConstrMenu->addAction("EXYZ", this, SLOT(addEXYZ()));
        ConstrMenu->addAction("EADP", this, SLOT(addEADP()));
        RestrMenu->addAction("RIGU", this, SLOT(addRIGU()));
        RestrMenu->addAction("DELU", this, SLOT(addDELU()));
        RestrMenu->addAction("SIMU", this, SLOT(addSIMU()));
        RestrMenu->addAction("CHIV", this, SLOT(addCHIV()));
      }
      menu->addMenu(RestrMenu);
      menu->addMenu(ConstrMenu);
    }else if (hasSameBonds) {
      QMenu *RestrMenu = new QMenu("Add restraints");
      QAction *restr;
      restr=RestrMenu->addAction("SADI", this, SLOT(addSADI()));
      restr->setData(idx);
      menu->addMenu(RestrMenu);
    }
    menu->addSeparator();
    QMenu *enviMenu = new QMenu("ENVI-Settings");
    enviMenu->addAction("Change envi range", this, SLOT(changeEnviRange()));
    enviMenu->addAction(enviNoQ);
    enviMenu->addAction(enviCova);
    menu->addMenu(enviMenu);
    if ((int) idx < mol->asymm.size()){
      a=menu->addAction(QString("List ENVIronment of %1").arg(mol->showatoms.at(idx).Label),this,SLOT(envi()));
      a->setData(idx);
    }
    menu->addSeparator();
    int ssgr=0;
    int adpat=0;
    for (int seli=0; seli<mol->selectedatoms.size(); seli++){
      if ((mol->showatoms.at(seli).symmGroup==0)&&(!mol->selectedatoms.at(seli).isIso))adpat++;
    }
    for (int seli=0; seli<mol->selectedatoms.size(); seli++){
      if (mol->selectedatoms.at(seli).symmGroup>0) ssgr+=mol->selectedatoms.at(seli).symmGroup;
      else {
        ssgr=0;
        break;
      }
    }
    if (ssgr) adpat=0;
    if (ssgr){
      a=menu->addAction(QString("Move selected atoms to selected sites"),
          chparent,SLOT(moveSymmMateSel()));
      //////// 28.03.12
      if (mol->showatoms.at(idx).part<0){
        a=menu->addAction(QString("Copy %1 here").arg(mol->showatoms.at(idx).Label.section("_",0,0)),
            chparent,SLOT(copySymmMate()));
        a->setData(idx);
      }
      //////// -
    }else{
      if (mol->showatoms.at(idx).symmGroup>0){
        a=menu->addAction(QString("Move %1 here").arg(mol->showatoms.at(idx).Label.section("_",0,0)),
            chparent,SLOT(moveSymmMate()));
        a->setData(idx);
        if (mol->showatoms.at(idx).part<0){
          a=menu->addAction(QString("Copy %1 here").arg(mol->showatoms.at(idx).Label.section("_",0,0)),
              chparent,SLOT(copySymmMate()));
          a->setData(idx);
        }

      }
    }
    menu->addSeparator();
    if ((nahdai<mol->asymm.size())&&(mol->knoepfe.at(idx).neighbors.size()==1)&&((mol->showatoms.at(idx).an==6)||(mol->showatoms.at(idx).an==5))) {

      //	printf("%s hat %d Nachbarn\n",mol->showatoms.at(idx).Label.toStdString().c_str(),mol->knoepfe.at(idx).neighbors.size());
      a=menu->addAction(QString("Add dissordered %1 Hydrogen atoms").arg(((mol->showatoms.at(idx).an==5))?"methyl":"-NH3"),chparent,SLOT(addDissorderedMethyl()));
      a->setData(idx);
      a=menu->addAction(QString("Add ordered %1 Hydrogen atoms").arg(((mol->showatoms.at(idx).an==5))?"methyl":"-NH3+"),chparent,SLOT(addMethyl()));
      a->setData(idx);
      a=menu->addAction(QString("Add terminal %1 Hydrogen atoms").arg(((mol->showatoms.at(idx).an==5))?"=CH2 ":"=NH2+"),chparent,SLOT(addH93()));
      a->setData(idx);
      if (mol->showatoms.at(idx).an==5){
        a=menu->addAction(QString("Add acetylenic C-H Hydrogen atom"),chparent,SLOT(addH163()));
        a->setData(idx);
      }
      if (mol->showatoms.at(idx).an==6){
        a=menu->addAction(QString("Add %1 Hydrogen atoms").arg("-NH2 (non planar)"),chparent,SLOT(addHnonplanarAminR1()));
        a->setData(idx);
      }      
    }
    if ((nahdai<mol->asymm.size())&&(mol->knoepfe.at(idx).neighbors.size()==1)&&(mol->showatoms.at(idx).an==7)){
        a->setData(idx);
        a=menu->addAction(QString("Add hydroxyl Hydrogen atom to %1").arg(mol->showatoms.at(idx).Label.section("_",0,0)),chparent,SLOT(addHydroxyl()));
        a->setData(idx);
    }
    if ((nahdai<mol->asymm.size())&&(mol->knoepfe.at(idx).neighbors.size()==2)&&((mol->showatoms.at(idx).an==6)||(mol->showatoms.at(idx).an==5))) {
      a=menu->addAction(QString("Add %1 Hydrogen atoms").arg(((mol->showatoms.at(idx).an==5))?">CH2":">NH2+"),chparent,SLOT(addH23()));
      a->setData(idx);
      a=menu->addAction(QString("Add %1 Hydrogen atom").arg(((mol->showatoms.at(idx).an==5))?">CH":">NH (planar)"),chparent,SLOT(addH43()));
      a->setData(idx);
      //addHnonplanarAminR2();
      if (mol->showatoms.at(idx).an==6){
        a=menu->addAction(QString("Add %1 Hydrogen atom").arg(">NH (non planar)"),chparent,SLOT(addHnonplanarAminR2()));
        a->setData(idx);
      }
    }
    if ((idx < mol->asymm.size()) && (mol->asymm.at(idx).an>-1)) {
      a=menu->addAction(QString("Use %1 as new label for rename mode").arg(mol->showatoms.at(idx).Label.section("_",0,0)),chparent,SLOT(renameThisAtom()));
      a->setData(idx);
    }

    if(!mol->selectedatoms.isEmpty()){
      menu->addAction(QString("Make selected atoms ANIS"),this,SLOT(addANIS()));
    }
    if (adpat) {
      if (mol->selectedatoms.isEmpty()){
        a=menu->addAction(QIcon(":/xle-icons/sina.svg"),QString("make %1 isotropic (ISOT)")
            .arg(mol->showatoms.at(idx).Label),chparent,SLOT(sina()));
        a->setData(idx);
      }else{
        a=menu->addAction(QIcon(":/xle-icons/sina.svg"),QString("make selected atoms isotropic (ISOT)"),chparent,SLOT(sina()));
        a->setData(-1);
      }
    }
    if ((idx<mol->asymm.size())&&(mol->asymm.at(idx).an>-1)){
        QAction *a = menu->addAction("Draw voronoi polyeder of this atom",chparent,SLOT(makeVoro()));
        a->setData(idx);
      }

    if (mol->showatoms.at(p).molindex!=mol->showatoms.at(idx).molindex){
      menu->addSeparator();
      a=menu->addAction(QString("Inherit Labels from molecule around %1 to atoms around %2")
          .arg(mol->showatoms.at(p).Label)
          .arg(mol->showatoms.at(idx).Label)
          ,chparent,SLOT(inheritLabels()));
      ppp = pp;
      pp = p;
      p = idx;

    }

    menu->exec(event->globalPos());
    delete enviMenu;
    delete menu;
  }
}

void ChGL::Listen(){//! forces the lists to be rerendered.
  murx=-__LINE__;
}

void ChGL::disSelection(){//! Un select everything.
  //rotCenter();
  QTime rzeit;
  rzeit.start();
  mol->selectedatoms.clear();
  apair.clear();
  updateBondActions();
  updateGL();
}

void ChGL::selectPair(const QString &s){
  apair.clear();
  //! Selelects two atoms from the spaces separated string s. @param space separated pair of atom labels. 
  mol->selectedatoms.clear();
  if (s.isEmpty()) {
    updateGL();
    return;
  }
  QStringList index=s.split(' ',skipEmptyParts);
  if (index.size()<2) {
    updateGL();
    return;
  }
  /*
   *
   length=b.length;
   ato1=b.ato1;
   ato2=b.ato2;
   a1=b.a1;
   a2=b.a2;
   */
  MyBond pair;
  pair.length=1.0;
  for (int i=0; i<index.size();i++){
    mol->selectedatoms.append(mol->showatoms[index.at(i).toInt()]);
    mol->selectedatoms.last().style=index.at(i).toInt();
    if (i==0){
      pair.ato1=&mol->selectedatoms.last();
      pair.a1=index.at(i).toInt();
    }else{
      pair.ato2=&mol->selectedatoms.last();
      pair.a2=index.at(i).toInt();
    }
  }
  //printf("a pair is made %d %d\n",pair.a1,pair.a2);
  apair.append(pair);
  //updateBondActions();
  updateGL();
}

void ChGL::pairing(QList<int> ima, QList<int> imb){
  MyBond pair;
  pair.length=1.0;
  for (int i=0; i<ima.size(); i++){
    pair.ato1=&mol->showatoms[ima.at(i)];
    pair.ato2=&mol->showatoms[imb.at(i)];
    pair.a1=ima.at(i);
    pair.a2=ima.at(i);
    apair.append(pair);
  }
  updateGL();
}

void ChGL::selectResiByNr(int nr){//! Selects atoms in residues with the same residue number. @param nr residue number.
  mol->selectedatoms.clear();  
  apair.clear();
  for (int i=0; i<mol->showatoms.size();i++){
    if (mol->showatoms.at(i).resiNr==nr) {
      mol->selectedatoms.append(mol->showatoms[i]);
      mol->selectedatoms.last().style=i;
    }
  }
  draw();
  if (hiddenThings) hideNonSelected();
  updateBondActions();
  updateGL();
}

void ChGL::invertSelection(){//!Inverts stelection, means selected atoms get disselected and vice versa.
  CEnvironment tempa=mol->selectedatoms;
  //  printf("invert %d %d\n",tempa.size(),mol->selectedatoms.size());
  mol->selectedatoms.clear();

  for (int i=0; i<mol->showatoms.size();i++){
    if (!tempa.contains(mol->showatoms.at(i))) {
      mol->selectedatoms.append(mol->showatoms[i]);
      mol->selectedatoms.last().style=i;
    }
  }
  draw();
  rehide();
  updateBondActions();
  updateGL();
}

void ChGL::updateBondActions(){//!<changes the visibility state of QActions in the 'Selection Toolbar'.
  bool p=pause;
  pause=true;
  clearSelection->setVisible(!mol->selectedatoms.isEmpty());
  invSelection->setVisible(!mol->selectedatoms.isEmpty());
  centroid->setVisible(mol->selectedatoms.size()>1);
  centerSelection->setVisible((!mol->selectedatoms.isEmpty())||(centerSelection->isChecked()));
  delSelAt->setVisible(!mol->selectedatoms.isEmpty());
  delSelAt->setEnabled(!mol->selectedatoms.isEmpty());
  hideNotSelection->setVisible(!mol->selectedatoms.isEmpty());
  cntrPlot->setVisible(((!fVertexes[0].isEmpty()||!fVertexes[1].isEmpty())&&(mol->selectedatoms.size()==3)));
  unhide->setVisible(hiddenThings);
  invhide->setVisible(hiddenThings);
  if (mol->selectedatoms.size()!=2){
    addBond->setVisible(false);
    killBond->setVisible(false);
  }
  else{
    int da=0;
    for (int i=0; i<mol->showbonds.size();i++){
      if (((mol->selectedatoms.at(0).style==mol->showbonds.at(i).a1)||
            (mol->selectedatoms.at(0).style==mol->showbonds.at(i).a2))&&
          ((mol->selectedatoms.at(1).style==mol->showbonds.at(i).a1)||
           (mol->selectedatoms.at(1).style==mol->showbonds.at(i).a2))) da=i;
    }
    if (da){
      addBond->setVisible(false);
      killBond->setVisible(true);
      killBond->setData(da);
    }
    else{
      addBond->setVisible(true);
      killBond->setVisible(false);
    }
  }
  pause=p;
}

void ChGL::connectSelection(){//!creates a bond betwen two selected atoms.
  if (mol->selectedatoms.size()!=2) return;
  MyBond b;
  b.a1=mol->selectedatoms.at(0).style;
  b.a2=mol->selectedatoms.at(1).style;
  b.ato1=&mol->showatoms[mol->selectedatoms.at(0).style];
  b.ato2=&mol->showatoms[mol->selectedatoms.at(1).style];
  b.length=sqrt(Distance(b.ato1->pos,b.ato2->pos));
  mol->showbonds.append(b);
  mol->selectedatoms.clear();
  updateBondActions();
  updateGL();
}

void ChGL::disConnectSelection(int index){//! destroyes the bond between two selected atoms.
  mol->showbonds.removeAt(index);
  mol->selectedatoms.clear();
  updateBondActions();
  updateGL();
}

void ChGL::setAtom(bool b){//!toggles atoms
  drawAt=b;
  updateGL();
}

void ChGL::setBond(bool b){//!toggles bonds
  drawBo=b;
  updateGL();
}

void ChGL::setLabel(bool b){//!toggles lables
  drawLa=b;
  updateGL();
}

void ChGL::setHBond(bool b){//!toggles H-bonds
  drawHb=b;
  updateGL();
}

void ChGL::setBGGradient(bool b){//!toggles back gound gradient
  bggradient=b;
  updateGL();
}

void ChGL::setADP(bool b){//!toggles ellipsoids
  drawADP=b;
  updateGL();
}

void ChGL::setMSAA(bool b){
  if (b) {
    glEnable(GL_MULTISAMPLE);
  }
  else  {
    glDisable(GL_MULTISAMPLE);
  }
  updateGL();
}

void ChGL::setUnit(bool b){//!toggles unit cell box
  drawUc=b;
  updateGL();
}

void ChGL::changeBColor(){//! a color dialog for chosing a new back ground color
  QColor bc= QColorDialog::getColor(backGroundColor, this);
  if(bc.isValid()) backGroundColor=bc;
  updateGL(); 
}

void ChGL::changeTColor(){//! a color dialog for chosing a label color
  QColor lc= QColorDialog::getColor(labelColor, this);
  if (lc.isValid()) labelColor=lc;
  updateGL(); 
}

void ChGL::setMolecule(Molecule *m){//! sets the pointer to the Molecule object deletes the old one if it is exists and is differen from the new one
  //  printf("setMolecule\n");
  if (mol!=m) {
    if (mol) delete mol;
    mol=m;  
  }
  double dim=mol->dimension();
  L=100.0/dim;
}

void ChGL::showMatrix(){
  //  stereo_mode++;
  //  stereo_mode%=4;
  updateGL();
  printf("The MMATRIX is:\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n",
      MM[0],MM[1],MM[2],MM[3],
      MM[4],MM[5],MM[6],MM[7],
      MM[8],MM[9],MM[10],MM[11],
      MM[12],MM[13],MM[14],MM[15]);
  GLdouble mm[16];
  glGetDoublev(GL_MODELVIEW_MATRIX,mm);
  printf("The Mmatrix is:\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n",
      mm[0],mm[1],mm[2],mm[3],
      mm[4],mm[5],mm[6],mm[7],
      mm[8],mm[9],mm[10],mm[11],
      mm[12],mm[13],mm[14],mm[15]);
  GLdouble det=
    mm[0]*mm[5]*mm[10] - mm[8]*mm[5]*mm[2]+
    mm[1]*mm[6]*mm[8]  - mm[9]*mm[6]*mm[0]+
    mm[2]*mm[4]*mm[9]  - mm[10]*mm[4]*mm[1];
  printf("die Determinante der Drehmatrix ist: %g\n",det);
  glGetDoublev(GL_PROJECTION_MATRIX,mm);
  printf("Die Pmatrix ist:\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n",
      mm[0],mm[1],mm[2],mm[3],
      mm[4],mm[5],mm[6],mm[7],
      mm[8],mm[9],mm[10],mm[11],
      mm[12],mm[13],mm[14],mm[15]);
  det=
    mm[0]*mm[5]*mm[10] - mm[8]*mm[5]*mm[2]+
    mm[1]*mm[6]*mm[8]  - mm[9]*mm[6]*mm[0]+
    mm[2]*mm[4]*mm[9]  - mm[10]*mm[4]*mm[1];
  printf("die Determinante der Drehmatrix ist: %g\n",det);
}

void ChGL::along001(){
  double va=viewAngle;
  setViewAngle(29.0);
  MM[0]=1.0;
  MM[1]=0.0;
  MM[2]=0.0;
  MM[4]=0.0;
  MM[5]=-1.0;
  MM[6]=0.0;
  MM[8]=0.0;
  MM[9]=0.0;
  MM[10]=-1.0;
  glMatrixMode(GL_MODELVIEW);
  glLoadMatrixd(MM);
  setViewAngle(va);
}

void ChGL::zoomOut(){
  double va=viewAngle;
  setViewAngle(29.0);
  glMatrixMode(GL_MODELVIEW);
  glGetDoublev(GL_MODELVIEW_MATRIX,MM);
  GLdouble det=
    MM[0]*MM[5]*MM[10] - MM[8]*MM[5]*MM[2]+
    MM[1]*MM[6]*MM[8]  - MM[9]*MM[6]*MM[0]+
    MM[2]*MM[4]*MM[9]  - MM[10]*MM[4]*MM[1];
  /*printf("Die Mmatrix ist:\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n",
      MM[0] ,MM[1] ,MM[2] ,MM[3],
      MM[4] ,MM[5] ,MM[6] ,MM[7],
      MM[8] ,MM[9] ,MM[10],MM[11],
      MM[12],MM[13],MM[14],MM[15]);
  printf("die Determinante der Matrix ist: %g\n",det);*/
  if (det !=0.0){
    det=pow(det,1.0/3.0);  
    MM[ 0]/=det;
    MM[ 1]/=det;
    MM[ 2]/=det;
    MM[ 4]/=det;
    MM[ 5]/=det;
    MM[ 6]/=det;
    MM[ 8]/=det;
    MM[ 9]/=det;
    MM[10]/=det;
    det=
      MM[0]*MM[5]*MM[10] - MM[8]*MM[5]*MM[2]+
      MM[1]*MM[6]*MM[8]  - MM[9]*MM[6]*MM[0]+
      MM[2]*MM[4]*MM[9]  - MM[10]*MM[4]*MM[1];
    /*printf("##Die Mmatrix ist:\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n%9.6f %9.6f %9.6f %9.6f\n",
        MM[0] ,MM[1] ,MM[2] ,MM[3],
        MM[4] ,MM[5] ,MM[6] ,MM[7],
        MM[8] ,MM[9] ,MM[10],MM[11],
        MM[12],MM[13],MM[14],MM[15]);
    printf("##die Determinante der Matrix ist: %g\n",det);*/

  }
  glLoadMatrixd(MM);
  setViewAngle(va);
}


void ChGL::initializeGL(){
  //printf("initGL\n");
  glEnable(GL_LINE_SMOOTH);   
  glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
  const GLfloat  position[] = {100.0f, 100.0f,100.0f,0.0f};
  const GLfloat  diffuse[]  = { 1.0, 1.0, 1.0, 1.0 };
  const GLfloat  specular[] = { 1.0, 1.0, 1.0, 1.0 };
  const GLfloat  ambient[]  = { 0.5, 0.5, 0.5, 1.0 };

  glLightModeli(  GL_LIGHT_MODEL_LOCAL_VIEWER, 1 );

  glLightfv( GL_LIGHT0, GL_POSITION, position );
  glLightfv( GL_LIGHT0, GL_AMBIENT,  ambient );
  glLightfv( GL_LIGHT0, GL_DIFFUSE,  diffuse );
  glLightfv( GL_LIGHT0, GL_SPECULAR, specular );

  glLightfv( GL_LIGHT1, GL_POSITION, position );
  glLightfv( GL_LIGHT1, GL_DIFFUSE,  diffuse );  
  glLightfv( GL_LIGHT1, GL_AMBIENT,  ambient );
  glLightfv( GL_LIGHT2, GL_DIFFUSE,  diffuse );  


  glEnable( GL_LIGHTING );
  glEnable( GL_LIGHT0 );
  glEnable( GL_BLEND);
  mol->fogrange=60;
  glDisable(GL_FOG);
  glFogi(GL_FOG_MODE,GL_LINEAR);
  glFogi(GL_FOG_START,205-mol->fogrange);
  glFogi(GL_FOG_END,205+mol->fogrange);
  GLfloat fgc[4]={(GLfloat)backGroundColor.redF(),(GLfloat)backGroundColor.greenF(),(GLfloat)backGroundColor.blueF(),1.0f};
  //printf("FOG %f %f %f %f\n",fgc[0],fgc[1],fgc[2],fgc[3]);
  glFogfv(GL_FOG_COLOR,fgc);

  glLightModeli(  GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  glAlphaFunc ( GL_GREATER, 0.01f ) ;
  glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
  const GLfloat  OBJ_SPE[]   = { 0.8f, 0.8f, 0.8f, 1.0f };
  const GLfloat  OBJ_SHIN    = 32.0;               
  glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR,             OBJ_SPE  );
  glEnable     ( GL_COLOR_MATERIAL ) ;
  glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;    
  glMaterialf(  GL_FRONT_AND_BACK, GL_SHININESS,           OBJ_SHIN );
  glShadeModel( GL_SMOOTH );
  //glShadeModel(GL_FLAT);
  glEnable(GL_NORMALIZE);

  qglClearColor(backGroundColor);

  glEnable(GL_DEPTH_TEST );
  glDepthFunc(GL_LEQUAL);
  gluLookAt_(0.0, 200, 50 ,   0.0, 0.0, 0.0,   0.0, -100, 400 );
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  setMouseTracking(true);
  //Listen inititialisieren ist hier!
  int ect=0;
#ifndef GL_MAX_ELEMENTS_INDICES
#define GL_MAX_ELEMENTS_INDICES           0x80E9
#endif /* GL_MAX_ELEMENTS_INDICES */
  int midx;
  glGetIntegerv(GL_MAX_ELEMENTS_INDICES,&midx);
  //printf("GL_MAX_ELEMENTS_INDICES = %d\n",midx);
  if (midx<3840)mol->LOD=qMin(mol->LOD,3);
  if (midx<940)mol->LOD=qMin(mol->LOD,2);
  GLenum err = GL_NO_ERROR;
  while((err = glGetError()) != GL_NO_ERROR)
  {
    printf("ganz davor %d %d [%d]\n",err==GL_INVALID_VALUE ,err == GL_INVALID_OPERATION,++ect); 
    // printf("%s\n",(char*)gluErrorString(err));
  }
  makeCurrent();
  const QGLContext *contxt = this->context();
  if (mol->g_Program==NULL){
    mol->g_Program= new QGLShaderProgram(contxt, this);
    mol->g_program=mol->installShader();
  }
  printf("shaderprog %d context is valid = %d \n",mol->g_program,contxt->isValid());
  if (!mol->g_program) printf("%s\n",mol->g_Program->log().toStdString().c_str());
  while((err = glGetError()) != GL_NO_ERROR)
  {
    printf("kurz davor GL_INVALID_VALUE%d GL_INVALID_OPERATION%d [%d] err=%x\n",err==GL_INVALID_VALUE ,err == GL_INVALID_OPERATION,++ect,err);
  }
  on=true;
  setupTexture();
  //printf("--initGL\n");
  // setViewAngle((orthoView)?0.2:29.0);
  //§§
  //mol->selectedatoms.append(newAtom);
  //§§
}


void ChGL::setRotationCenter(){
  //! Sets the rotation center to the spezified atom
  QAction *action = qobject_cast<QAction *>(sender());
  int index=0;
  if (action)
    index=action->data().toInt();
  else return;
  if (index==(int)((GLuint)-1))return;
  rotze=((int)index<mol->showatoms.size())?index:-1;
  if (rotze>-1){ 
    rCenter->show();
    glGetDoublev(GL_MODELVIEW_MATRIX,MM);
    MM[12]=MM[13]=0;
    glLoadMatrixd(MM);
  }
  updateGL();
}

void ChGL::setRotationCenter(V3 center){
 // printf("%f %f %f \n%f %f %f\n", altemitte.x, altemitte.y, altemitte.z, center.x, center.y, center.z);
  altcenter=center;
  rotze=-76185;//zip code
  rCenter->show();
  updateGL();
}


void ChGL::setRotationCenter(int rz){
  /*! Sets the rotation center to the spezified atom
   * @param index of the spezified atom.
   */
  rotze=((int)rz<mol->showatoms.size())?rz:-1;
  if (rotze>-1){
    rCenter->show();
    glGetDoublev(GL_MODELVIEW_MATRIX,MM);
    MM[12]=MM[13]=0;
    glLoadMatrixd(MM);
  }
  updateGL();
}

void ChGL::expand(){//! Lets Molecule.expandAt(int index) serach for neighboring molecules around the specified atom. 
  QAction *action = qobject_cast<QAction *>(sender());
  int index=0;
  if (action)
    index=action->data().toInt();
  else return;
  if (index==(int)((GLuint)-1))return;
  mol->expandAt(index);
  fuse->setVisible(true);
  grow->setVisible(false);
  emit bigmessage(mol->HumanSymmetry);
  murx=-__LINE__;
  updateGL();
}

void ChGL::incFontSize(){//! increases label font size
  myFont.setPointSize(myFont.pointSize()+1);
  updateGL();
}

void ChGL::decFontSize(){//! decreases label font size
  myFont.setPointSize(qMax(myFont.pointSize()-1,7));
  updateGL();

}

void ChGL::updateLabelTextures(){
  labelTextures.clear();
  for (int li=0; li<mol->showatoms.size(); li++){
    QFont fnt=myFont;
    fnt.setPointSize((mol->showatoms.at(li).an>=0)?144:96);
    QFontMetrics mtr(myFont);
    QString label=mol->showatoms.at(li).Label;
    if (shortLabels->isChecked()) {
      label=label.section("_",0,0);
      label=label.section(QString::fromUtf8("»"),0,0);
    }
    QRect rc=mtr.boundingRect(label);
    QImage image(rc.width()+mtr.width("Li"), rc.height()+2,QImage::Format_ARGB32_Premultiplied);
    //printf("texture %d  %d x %d Pts = %d\n",li,image.width(),image.height(),fnt.pointSize());

    image.fill(0);
    QPainter p;
    p.begin(&image);
    p.setPen(QPen(Qt::white));
    p.setBackground(Qt::NoBrush);
    p.setFont(myFont);
    p.drawText(image.rect(), Qt::AlignRight, label);
    p.end();
    image=image.convertToFormat(QImage::Format_Indexed8);
    labelTextures.append(image);
  }
  extraTextures.clear();
  QStringList lala;
  lala<<"0"<<"a"<<"b"<<"c";
  for (int i=0; i<mol->legendAtoms.size(); i++){
    lala.append(mol->legendAtoms.at(i).Label);
  }
  for (int i=0; i<lala.size();i++){
    QFont fnt=myFont;
    fnt.setPointSize(96);
    QFontMetrics mtr(myFont);
    QRect rc=mtr.boundingRect(lala.at(i));
    QImage image(rc.width()+mtr.width("Li"),rc.height(),QImage::Format_ARGB32_Premultiplied);
    image.fill(0);
    QPainter p;
    p.begin(&image);
    p.setPen(QPen(Qt::white));
    p.setBackground(Qt::NoBrush);
    p.setFont(myFont);
    p.drawText(image.rect(), Qt::AlignRight, lala.at(i));
    p.end();
    image=image.convertToFormat(QImage::Format_Indexed8);
    extraTextures.append(image);
  }

  updateGL();

}

//#include <iostream>
void ChGL::setReNaMo(bool b){//!enter rename mode 
  inRenameMode=b;
}

void ChGL::rotCenter(){//! reset the rotation center to the center of gravity.
  rotze=-1;
  updateGL();
  rCenter->hide();
}

void ChGL::resizeGL(int width, int height) {
  if (pause) {ww=width; wh=height; return;}
  GLint v[2];
  glGetIntegerv(GL_MAX_VIEWPORT_DIMS,v);
  //printf("MAXVP %d %d \n",v[0],v[1]);
  glViewport(0, 0, ww=width, wh=height);
  glGetIntegerv(GL_VIEWPORT, vp);
  retinafktr=ww/this->width();
  //printf("VP %d %d %d %d  w=%d h=%d  %d %d\n",vp[0],vp[1],vp[2],vp[3],ww,wh,this->width(),this->height());
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective_( viewAngle, (double)width/height, 5.0, 8000.0 );
}

void ChGL::zoom(double speed){//!scale about speed @param speed scale factor
  moving->start(dratpause);
  //  printf("%d\n",dratpause);
  glScaled(1.0+speed*0.1,1.0+speed*0.1,1.0+speed*0.1);  
  updateGL();  
}

void ChGL::rotY(double speed){//!rotate around Y axis @param speed in degrees
  moving->start(dratpause);
  glRotateL(-20.0*speed,0.0f,1.0f,0.0f);
  updateGL();  
}

void ChGL::gZoom(double speed){//!scale about speed @param speed scale factor 
  moving->start(dratpause);
  glScaled(1.0+speed*0.02,1.0+speed*0.02,1.0+speed*0.02);
  updateGL();
}

void ChGL::rotZ(double speed){//!rotate around Z axis @param speed in degrees  
  moving->start(dratpause);
  glRotateL(speed,0.0f,0.0f,1.0f);
  updateGL();
}

void ChGL::moveY(double speed){//!translate the molecule in Y direction
  moving->start(dratpause);
  glTranslateL(0.0,speed,0.0);
  updateGL();  
}

void ChGL::moveX(double speed){//!translate the molecule in X direction
  moving->start(dratpause);
  glTranslateL(speed,0.0,0.0);
  //  QMessageBox::information(this,"Px move","xmoved",QMessageBox::Ok);
  updateGL();  
}

void ChGL::rotX(double speed){//!rotate around X axis @param speed in degrees
  moving->start(dratpause);
  glRotateL(-20.0*speed,1.0f,0.0f,0.0f);
  updateGL();  
}


void ChGL::zalman(){//!sets the stereo mode for Zalman monitors.
  stereo_mode=1;
  minus= 1;
  updateGL();
}

QStringList ChGL::resis(){
  QStringList l;
  for (int i=0; i<mol->asymm.size(); i++){
      if (mol->asymm.at(i).an<0)continue;
    if (mol->asymm.at(i).resiNr>0){
      if (!l.contains(QString::number(mol->asymm.at(i).resiNr),Qt::CaseInsensitive))
        l.append(QString::number(mol->asymm.at(i).resiNr));
      if (!l.contains(mol->asymm.at(i).ResiClass))
        l.append(mol->asymm.at(i).ResiClass);
    }
  }
  if (!l.isEmpty()) l.insert(0,"*");
  return l;
}

void ChGL::singleBondDistance(){
    if (mol->selectedatoms.size()!=2)return;
    QWidgetList wl = QApplication::allWidgets();
    for (int i=0; i<wl.size(); i++){
        if (wl.at(i)->objectName()=="DFIX_DIST"){
            QLineEdit *valueline = qobject_cast<QLineEdit *>(wl[i]);
            valueline->setText(QString::number(0.01*(mol->Kovalenz_Radien[mol->selectedatoms.at(0).an]+mol->Kovalenz_Radien[mol->selectedatoms.at(1).an]),10,3));
        }
    }
}

void ChGL::addDFIX(){
    if (mol->selectedatoms.size()!=2)return;
  QDialog *dia = new QDialog();
  dia->setWindowTitle("DFIX: Geometrical restraint");
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *valueline = new QLineEdit(dia);
  valueline->setObjectName("DFIX_DIST");
  QLineEdit *esdline = new QLineEdit(dia);
  QLabel *value = new QLabel("Value:", dia);
  QLabel *esd = new QLabel("ESD:", dia);
  QLabel *atoms = new QLabel(QString("%1==%2  : %3 A")
                             .arg(mol->selectedatoms.at(0).Label)
                             .arg(mol->selectedatoms.at(1).Label)
                             .arg( sqrt(Distance(mol->selectedatoms.at(0).pos,mol->selectedatoms.at(1).pos)),10,'f',3));
  QCheckBox *bindit = new QCheckBox("Insert BIND instruction",dia);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific",dia);
    resiCom = new QComboBox(dia);
    // Usually you want to define residue restraints with numbers at the atom:
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,3,0);
    grid->addWidget(resiCom,3,1);
  }
  // Set default value for distance and esd
  // Get value for DFIX. Current bond distance and default esd - 0.02
  valueline->setText(QString::number(sqrt(Distance(mol->selectedatoms.at(0).pos,mol->selectedatoms.at(1).pos)),10,3));
  esdline->setText("0.02");
  grid->addWidget(atoms,0,0,1,2);
  grid->addWidget(value,1,0);
  grid->addWidget(valueline,1,1);
  grid->addWidget(esd,2,0);
  grid->addWidget(esdline,2,1);
  grid->addWidget(bindit,4,0);
  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;
  QPushButton *singleBondButton = new QPushButton(QString("%1 A").arg(0.01*(mol->Kovalenz_Radien[mol->selectedatoms.at(0).an]+mol->Kovalenz_Radien[mol->selectedatoms.at(1).an])));

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);
  buttonBox->addButton(singleBondButton,QDialogButtonBox::ActionRole);


  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,10,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));
  connect(singleBondButton, SIGNAL(clicked()), this, SLOT(singleBondDistance()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertDFIX(valueline->text().toDouble(),esdline->text().toDouble(),mol->selectedatoms,s);
    if (bindit->isChecked()) emit bindthem();
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();

  }


  //    updateBondActions();
}

void ChGL::addDANG(){
  QDialog *dia = new QDialog(this);
  dia->setWindowTitle(tr("DANG: Geometrical restraint"));
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *valueline = new QLineEdit(dia);
  QLineEdit *esdline = new QLineEdit(dia);
  QLabel *value = new QLabel("Value:", dia);
  QLabel *esd = new QLabel("ESD:", dia);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific",dia);
    resiCom = new QComboBox(dia);
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,2,0);
    grid->addWidget(resiCom,2,1);
  }
  // Set default value for distance and esd
  // Get value for DANG. Current bond distance and default esd - 0.04
  valueline->setText(QString::number(sqrt(Distance(mol->selectedatoms.at(0).pos,mol->selectedatoms.at(1).pos)),10,3));
  esdline->setText("0.04");

  grid->addWidget(value,0,0);
  grid->addWidget(valueline,0,1);
  grid->addWidget(esd,1,0);
  grid->addWidget(esdline,1,1);

  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);

  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,4,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertDANG(valueline->text().toDouble(),esdline->text().toDouble(),mol->selectedatoms,s);
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();
  }

}

void ChGL::addFLAT(){
  QDialog *dia = new QDialog(this);
  dia->setWindowTitle(tr("FLAT: Geometrical restraint"));
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *esdline = new QLineEdit(dia);
  QLabel *esd = new QLabel("ESD:", dia);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific",dia);
    resiCom = new QComboBox(dia);
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,2,0);
    grid->addWidget(resiCom,2,1);
  }
  // Set default value for esd
  esdline->setText("0.1");

  grid->addWidget(esd,0,0);
  grid->addWidget(esdline,0,1);

  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);

  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,1,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertFLAT(esdline->text().toDouble(),mol->selectedatoms,s);
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();
  }

}

void ChGL::addEXYZ(){
  emit insertEXYZ(mol->selectedatoms);
  mol->selectedatoms.clear();
}

void ChGL::addEADP(){
  emit insertEADP(mol->selectedatoms);
  mol->selectedatoms.clear();
}

void ChGL::addDELU(){
  QDialog *dia = new QDialog(this);
  dia->setWindowTitle(tr("DELU: ADP restraint"));
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *esd1line = new QLineEdit(dia);
  QLineEdit *esd2line = new QLineEdit(dia);
  QLabel *esd1 = new QLabel("ESD1:", dia);
  QLabel *esd2 = new QLabel("ESD2:", dia);
  // Set default value for distance and esd
  esd1line->setText("0.01");
  esd2line->setText("0.01");

  grid->addWidget(esd1,0,0);
  grid->addWidget(esd1line,0,1);
  grid->addWidget(esd2,1,0);
  grid->addWidget(esd2line,1,1);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific",dia);
    resiCom = new QComboBox(dia);
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,3,0);
    grid->addWidget(resiCom,3,1);
  }

  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);

  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,4,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertDELU(esd1line->text().toDouble(),esd2line->text().toDouble(),mol->selectedatoms,s);
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();
  }
}

void ChGL::addSIMU(){
  QDialog *dia = new QDialog(this);
  dia->setWindowTitle(tr("SIMU: ADP restraint"));
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *esd1line = new QLineEdit(dia);
  QLineEdit *esd2line = new QLineEdit(dia);
  QLineEdit *dmaxline = new QLineEdit(dia);
  QLabel *esd1 = new QLabel("ESD1:", dia);
  QLabel *esd2 = new QLabel("ESD2:", dia);
  QLabel *dmax = new QLabel("dmax:", dia);
  // Set default value for distance and esd
  esd1line->setText("0.04");
  esd2line->setText("0.08");
  dmaxline->setText("2.00");

  grid->addWidget(esd1,0,0);
  grid->addWidget(esd1line,0,1);
  grid->addWidget(esd2,1,0);
  grid->addWidget(esd2line,1,1);
  grid->addWidget(dmax,2,0);
  grid->addWidget(dmaxline,2,1);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific", dia);
    resiCom = new QComboBox(dia);
    // Usually you want to define residue restraints with numbers at the atom:
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,3,0);
    grid->addWidget(resiCom,3,1);
  }

  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);

  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,4,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertSIMU(esd1line->text().toDouble(),esd2line->text().toDouble(),dmaxline->text().toDouble(),mol->selectedatoms,s);
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();
  }

}

void ChGL::addSADI() {
  //! Adds SADI restraints between the selected atom and all bonded atoms.
  QAction *action = qobject_cast<QAction *>(sender());
  int index=-1;
  if (action)
    index=action->data().toInt();
  else index=-1;
  if (index>mol->asymm.size()) index=-1;
  if (index!=-1) {
    emit insertSADI(index);
  }
}

void ChGL::addISOR(){
  QDialog *dia = new QDialog(this);
  dia->setWindowTitle(tr("ISOR: ADP restraint"));
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *esd1line = new QLineEdit(dia);
  QLineEdit *esd2line = new QLineEdit(dia);
  QLabel *esd1 = new QLabel("ESD1:", dia);
  QLabel *esd2 = new QLabel("ESD2:", dia);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific",dia);
    resiCom = new QComboBox(dia);
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,3,0);
    grid->addWidget(resiCom,3,1);
  }
  // Set default values for s and st
  esd1line->setText("0.1");
  esd2line->setText("0.2");

  grid->addWidget(esd1,0,0);
  grid->addWidget(esd1line,0,1);
  grid->addWidget(esd2,1,0);
  grid->addWidget(esd2line,1,1);

  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);

  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,4,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertISOR(esd1line->text().toDouble(),esd2line->text().toDouble(),mol->selectedatoms,s);
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();
  }
}

void ChGL::addRIGU(){
  QDialog *dia = new QDialog(this);
  dia->setWindowTitle(tr("RIGU: ADP restraint"));
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *esd1line = new QLineEdit(dia);
  QLineEdit *esd2line = new QLineEdit(dia);
  QLabel *esd1 = new QLabel("ESD1:", dia);
  QLabel *esd2 = new QLabel("ESD2:", dia);
  // Set default value for distance and esd
  esd1line->setText("0.004");
  esd2line->setText("0.004");
  int i(0); // index for position of widgets in the container
  grid->addWidget(esd1,i,0);
  grid->addWidget(esd1line,i++,1);
  grid->addWidget(esd2,i,0);
  grid->addWidget(esd2line,i++,1);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific",dia);
    resiCom = new QComboBox(dia);
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,i,0);
    grid->addWidget(resiCom,i++,1);
  }

  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);

  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,i,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertRIGU(esd1line->text().toDouble(),esd2line->text().toDouble(),mol->selectedatoms,s);
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();
  }
}

void ChGL::addCHIV(){
  QDialog *dia = new QDialog(this);
  dia->setWindowTitle(tr("CHIV: Geometrical restraint"));
  dia->setModal(false);

  QGridLayout *grid = new QGridLayout(dia);
  QLineEdit *volline = new QLineEdit(dia);
  QLineEdit *esd1line = new QLineEdit(dia);
  QLabel *vol = new QLabel("Volume:", dia);
  QLabel *esd1 = new QLabel("ESD:", dia);
  // Set default value for distance and esd
  volline->setText("0.0");
  esd1line->setText("0.1");
  int i(0); // index for position of widgets in the container
  grid->addWidget(vol,i,0);
  grid->addWidget(volline,i++,1);
  grid->addWidget(esd1,i,0);
  grid->addWidget(esd1line,i++,1);
  QStringList rl = resis();
  QComboBox *resiCom = NULL;
  if (!rl.isEmpty()){
    QLabel *resi = new QLabel("Residue specific",dia);
    resiCom = new QComboBox(dia);
    resiCom->addItem("");
    resiCom->addItems(rl);
    grid->addWidget(resi,i,0);
    grid->addWidget(resiCom,i++,1);
  }

  QDialogButtonBox *buttonBox = new QDialogButtonBox();

  QPushButton *OkButton;
  QPushButton *CancelButton;

  OkButton = buttonBox->addButton(QDialogButtonBox::Ok);
  CancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);

  buttonBox->setOrientation(Qt::Horizontal);

  grid->addWidget(buttonBox,i,0);

  dia->setLayout(grid);
  connect(OkButton, SIGNAL(clicked()), dia, SLOT(accept()));
  connect(CancelButton, SIGNAL(clicked()), dia, SLOT(reject()));

  dia->show();
  int a  = dia->exec();

  if(a == QDialog::Accepted)
  {
    // read value from value line
    QString s=(rl.isEmpty())?"":resiCom->currentText();
    emit insertCHIV(volline->text().toDouble(),esd1line->text().toDouble(),mol->selectedatoms,s);
    mol->selectedatoms.clear();
  }
  else
  {
    if(a == QDialog::Rejected)
      dia->close();
  }
}

void ChGL::addANIS()
{
  emit insertANIS(mol->selectedatoms);
  mol->selectedatoms.clear();
}


void ChGL::parallel(){//!sets the stereo mode for parallel eye side by side stereo
  stereo_mode=2;
  minus=1;
  updateGL();
}

void ChGL::crosseye(){//!sets the stereo mode for crossed eye side by side stereo
  stereo_mode=3;
  minus=-1;
  updateGL();
}

void ChGL::anaglyphRedCyan(){//!sets the stereo mode for analglyph stereo Red and Cyan glasses. 
  stereo_mode=4;
  minus=1;
  updateGL();
}

void ChGL::hardwareStereo(){//!sets the stereo mode for hardware or driver supported stereo mode
  if (format().stereo()){
    stereo_mode=5;
    minus=-1;
    updateGL();
  }
  else {
    qDebug()<<"no stereo sorry!";
    emit no_hw_st();
  }
}

void ChGL::nostereo(){//!turns the stereo mode off
  stereo_mode=0;
  updateGL();
}

void ChGL::clearEnvi(){ 
  /*! Clears ChGL.enviPositions, ChGL.enviKat. and ChGL.labs */
  enviPositions.clear();
  labs.clear();
  enviKat.clear();
  enviButt->setVisible(false);
  enviSelect->setVisible(false);
  rotCenter();
}

void ChGL::selectEnvi(){
  mol->selectedatoms.clear();
  if (rotze>=0) {
    mol->selectedatoms.append(mol->showatoms[rotze]);
    mol->selectedatoms.last().style=rotze;
  }
  for (int i=0; i<mol->showatoms.size(); i++){
    for (int j=0; j< enviPositions.size(); j++){
      if (mol->showatoms.at(i).pos==enviPositions.at(j)) {
        mol->selectedatoms.append(mol->showatoms[i]);
        mol->selectedatoms.last().style=i;
      }
    }
  }
  updateBondActions();
  updateGL();

}

void ChGL::envi(){
  /*! Finds neighboring atoms around a ChGL.envirange the spezified atom and passes a html table via ChGL.bigmessage
   * Feeds ChGL.enviPositions, ChGL.labs  and ChGL.enviKat. 
   * sets the rotation center to the spezified atom.
   * */    
 // printf("->-ENVI-<-\n");
  QAction *action = qobject_cast<QAction *>(sender());
  int index=0;
  if (action)
    index=action->data().toInt();
  else index=rotze;//return;
  if (index<0) return;
  if (index>=mol->asymm.size())return;
  mol->enviSDM(envirange);
  enviPositions.clear();
  enviKat.clear();
  labs.clear();
  QList<bool> covs;
  pause=true;

  V3 ppc,ppf,p0;
  // int ssy=0;
  QString systr;
  QStringList bs;
  QString info;
  enviP0=mol->asymm.at(index).pos;
  info.append(QString("<hr><b>Environment of %1 </b><table border=\"0\" cellspacing=\"0\" cellpadding=\"5\">").arg(mol->asymm[index].Label));
  for (int i = 0; i < mol->envi_sdm.size(); i++){
    if ((mol->envi_sdm.at(i).a2==index)&&mol->envi_sdm.at(i).d<envirange) {
      if ((!mol->envi_sdm.at(i).covalent)&&(enviCova->isChecked())) continue;
      if ((mol->asymm[mol->envi_sdm.at(i).a1].an==-1)&&(enviNoQ->isChecked())) continue;
      ppf=mol->cell.symmops.at(mol->envi_sdm.at(i).sn) *
        mol->asymm[mol->envi_sdm.at(i).a1].frac +
        mol->cell.trans.at(mol->envi_sdm.at(i).sn) -//-
        mol->envi_sdm.at(i).floorD;
      mol->frac2kart(ppf,ppc);
      mol->frac2kart(mol->asymm[index].frac,p0);
      /*
         if (fabs(mol->envi_sdm.at(i).d-sqrt(Distance(p0,ppc)))>0.5){
         ppf=mol->cell.symmops.at(mol->envi_sdm.at(i).sn) *
         mol->asymm[mol->envi_sdm.at(i).a2].frac -
         mol->cell.trans.at(mol->envi_sdm.at(i).sn) -
         mol->envi_sdm.at(i).floorD;
         mol->frac2kart(ppf,ppc);

         }// */
      enviPositions.append(ppc);
      covs.append(mol->envi_sdm.at(i).covalent);
      enviKat.append((mol->envi_sdm.at(i).covalent)?1:0);
      if((abs(mol->asymm[mol->envi_sdm.at(i).a1].an-7)<2)
          &&(abs(mol->asymm[mol->envi_sdm.at(i).a2].an-7)<2)
          &&(fabs(mol->envi_sdm.at(i).d-2.725)<0.275)){enviKat.last()=2;}

      if((mol->asymm[mol->envi_sdm.at(i).a1].an==0)&&(abs(mol->asymm[mol->envi_sdm.at(i).a2].an-7)<2)&&(fabs(mol->envi_sdm.at(i).d-1.875)<0.275)){enviKat.last()=2;}
      if((mol->asymm[mol->envi_sdm.at(i).a2].an==0)&&(abs(mol->asymm[mol->envi_sdm.at(i).a1].an-7)<2)&&(fabs(mol->envi_sdm.at(i).d-1.875)<0.275)){enviKat.last()=2;}
      bool symm=((mol->envi_sdm.at(i).sn)||(!(mol->envi_sdm.at(i).floorD==V3(0,0,0))));
      if (symm) {
        QString sss=QString("%1_%2%3%4:%5,").arg(mol->envi_sdm.at(i).sn+1).arg(5-(int)mol->envi_sdm.at(i).floorD.x).arg(5-(int)mol->envi_sdm.at(i).floorD.y).arg(5-(int)mol->envi_sdm.at(i).floorD.z).arg(mol->asymm[mol->envi_sdm.at(i).a1].molindex);
        if (!bs.contains(sss)){
          bs.append(sss);
        }

        systr=QString("%1%2").arg(QString::fromUtf8("»")).arg(bs.indexOf(sss)+1);
        labs.append(mol->asymm[ mol->envi_sdm.at(i).a1].Label+systr);
      }
      else labs.append(mol->asymm[ mol->envi_sdm.at(i).a1].Label);
      info.append(QString("<tr><th style=\"background:%6\" >%1%4</th><td style=\"background:%5\" >%7<font color=%3> %2&nbsp;&Aring;</font></b></td>")
          .arg(mol->asymm[ mol->envi_sdm.at(i).a1].Label)
          .arg(mol->envi_sdm.at(i).d,8,'f',3)
          .arg((mol->envi_sdm.at(i).covalent)?"green":"black")
          .arg(symm?systr:"").arg((labs.size()%2)?"#eeeeee":"white")
          .arg((labs.size()%2)?"#d4d4e4":"#efefff")
          .arg((mol->envi_sdm.at(i).covalent)?"<b>":""));
      for (int j=0; j<enviPositions.size()-1; j++){
        double w=
          mol->winkel(p0-enviPositions.at(j),
              p0-enviPositions.last());
        //		printf("%s-%s-%s %g   %g %g %g\n",labs.at(j).toStdString().c_str(),mol->asymm[index].Label.toStdString().c_str(),labs.last().toStdString().c_str(),w,enviPositions.at(j).x ,enviPositions.at(j).y,enviPositions.at(j).z);
        info.append(QString("<td style=\"background:%3\" align=right>%4<font color=%2> %1&deg;</font></b></td>")
            .arg(w,8,'f',2)
            .arg(((mol->envi_sdm.at(i).covalent)&&(covs.at(j)))?"green":"black")
            .arg(((j+1)%2)?(labs.size()%2)?"#d4d4d4":"#e4e4e4":(labs.size()%2)?"#eeeeee":"#ffffff")
            .arg(((mol->envi_sdm.at(i).covalent)&&(covs.at(j)))?"<b>":""));

      }
      info.append("</tr>\n");
    }
  }
  info.append("<tr><td style=\"background:#efefff\"></td><td style=\"background:#efefff\"></td>");
  for (int j=0; j<enviPositions.size()-1; j++){
    info.append(QString("<th style=\"background:%2\">%1</th>").arg(labs.at(j)).arg(((j+1)%2)?"#d4d4e4":"#efefff"));
  }
  QString symml="";
  for (int j=0; j<bs.size(); j++){
    symml+=mol->symmcode2human(bs.at(j),j+1);
  }
  info.append(QString("</tr>\n</table>%1<hr>\n").arg(symml));

  enviTextures.clear();
  QFont fnt=myFont;
  fnt.setPointSize(96);
  QFontMetrics mtr(myFont);
  for (int li=0; li<labs.size(); li++){
    QString label=labs.at(li);
    int rcw=mtr.width(label);
    QImage image(rcw+mtr.width("Li"), mtr.height()+2,QImage::Format_ARGB32_Premultiplied);
    image.fill(0);
    QPainter p;
    p.begin(&image);
    p.setPen(QPen(Qt::white));
    p.setBackground(Qt::NoBrush);
    p.setFont(myFont);
    //p.drawRect( 1, 1, image.rect().width()-3, image.rect().height()-3 );
    p.drawText(5,image.rect().height()-3, label);
    p.end();
    enviTextures.append(image.convertToFormat(QImage::Format_Indexed8));
  }
  for (int j=0; j<enviPositions.size()-1; j++){
      QString label=QString::number(sqrt(Distance(enviP0,enviPositions.at(j))),'f',3);
      label.append("Ang");
      int rcw=mtr.width(label);
      QImage image(rcw+4, mtr.height()+4,QImage::Format_ARGB32_Premultiplied);
      image.fill(0);
      QPainter p;
      p.begin(&image);
      p.setPen(QPen(Qt::white));
      p.setBackground(Qt::NoBrush);
      p.setFont(myFont);
      p.drawText(0,image.rect().height()-10, label);
      //p.drawRect( 1, 1, image.rect().width()-3, image.rect().height()-3 );
      p.end();
      enviTextures.append(image.convertToFormat(QImage::Format_Indexed8));
  }
  emit bigmessage(info);

  enviButt->setVisible(true);
  enviSelect->setVisible(true);
  pause=false;
  setRotationCenter(index);
 // printf("--ENVI--\n");
}

void ChGL::setDepthCueing(bool b){
    depthcueing=b;
    mol->mist=b;
    updateGL();

}

void ChGL::paintGL(){
  //  printf("%d pause%d\n",__LINE__,pause);
  /*
     static QGLFunctions *glf= new QGLFunctions(context());
     printf ("!!! %p\n",glf);
     GLenum stat =  glf->glCheckFramebufferStatus(GL_FRAMEBUFFER);
     printf("%x %x\n",stat, GL_FRAMEBUFFER_COMPLETE);
     if (stat!= GL_FRAMEBUFFER_COMPLETE) return;
     */

  if (!moving->isActive()) mol->dratom=0;
  if (pause)  return;
  GLenum err = GL_NO_ERROR;
  while((err = glGetError()) != GL_NO_ERROR)
  {
    printf("0paintGL %s err=%X\n",glError2String(err).toStdString().c_str(),err);
    //printf("%s\n",(char*)gluErrorString(err));
  }
  //if ((viewAngle>0.3)&&(orthoView)&&(mol->showatoms.size()>0)) setViewAngle((orthoView)?0.2:29.0);
  warLabel = drawLa;
  qglClearColor(backGroundColor);
  mol->fgc[0] = (GLfloat)backGroundColor.redF();
  mol->fgc[1] = (GLfloat)backGroundColor.greenF();
  mol->fgc[2] = (GLfloat)backGroundColor.blueF();
  mol->fgc[3] = 1.0f;
  glFogfv(GL_FOG_COLOR,mol->fgc);
  glViewport(0, 0, ww, wh);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  //  printf("clear %d %d\n",ww,wh);
  glViewport(0, 0, ww, wh);
  glDisable(GL_STENCIL_TEST);
  glGetIntegerv(GL_VIEWPORT, vp);
  if (!stereo_mode){
    //  printf("%d %d %d %d \n",vp[0],vp[1],vp[2],vp[3]);
    glDrawBuffer(GL_BACK);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    if (!pause) draw();
    glPopMatrix();
  }else 
    if (stereo_mode==1){// stereo zalman
      glDrawBuffer(GL_BACK);
      GLint viewport[4];
      glGetIntegerv(GL_VIEWPORT,viewport);

      glPushAttrib(GL_ENABLE_BIT);
      glMatrixMode(GL_PROJECTION);
      glPushMatrix();
      glLoadIdentity();
      glOrtho(0,viewport[2],0,viewport[3],-10.0,10.0);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glLoadIdentity();
      glTranslatef(0.33F,0.33F,0.0F); 
      glDisable(GL_STENCIL_TEST);
      glDisable(GL_ALPHA_TEST);
      glDisable(GL_LIGHTING);
      glDisable(GL_FOG);
      glDisable(GL_NORMALIZE);
      glDisable(GL_DEPTH_TEST);
      glDisable(GL_COLOR_MATERIAL);
      glDisable(GL_LINE_SMOOTH);
      glDisable(GL_DITHER);
      glDisable(GL_BLEND);
      glShadeModel(GL_SMOOTH);

      glClearStencil(0);
      glColorMask(false,false,false,false);
      glDepthMask(false);
      glClear(GL_STENCIL_BUFFER_BIT);

      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_ALWAYS, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

      glLineWidth(1.0);
      glBegin(GL_LINES);
      int h = viewport[3], w=viewport[2];
      int y;
      for(y=0;y<h;y+=2) {
        glVertex2i(0,y);
        glVertex2i(w,y);
      }
      glEnd();

      glColorMask(true,true,true,true);
      glDepthMask(true);

      glMatrixMode(GL_MODELVIEW);
      glPopMatrix();
      glMatrixMode(GL_PROJECTION);
      glPopMatrix();
      //
      glPopAttrib();

      glViewport(0, 0, ww, wh);        
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glViewport(0, 0, ww, wh);        
      glGetIntegerv(GL_VIEWPORT, vp);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      drawLa=false;
      glRotateL(minus*-1.5,0,1,0);
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_EQUAL, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
      glEnable(GL_STENCIL_TEST);// */
      if (!pause) draw();
      glPopMatrix();

      drawLa= warLabel;
      glPushMatrix();
      glRotateL(minus*1.5,0,1,0);
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_EQUAL, 0, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
      glEnable(GL_STENCIL_TEST);// */
      if (!pause) draw();
      glPopMatrix();
    }else  
      if ((stereo_mode>1)&&(stereo_mode<4)) { //stereo_side by side
        glDrawBuffer(GL_BACK);
        glPushMatrix();
        glViewport(0, 0, ww/2, wh);        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective_( viewAngle, (double)(ww/2.0)/wh, 5.0, 8000.0 );
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glRotateL(1.5*minus,0,1,0);
        if (!pause) draw();
        glPopMatrix();
        glPopMatrix();
        glPushMatrix();
        glViewport( ww / 2 , 0,ww / 2,wh );        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective_( viewAngle, (double)(ww/2.0)/wh, 5.0, 8000.0 );
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glRotateL(-1.5*minus,0,1,0);
        if (!pause) draw();
        glPopMatrix();
        glPopMatrix();

      }
      else  if (stereo_mode==4){//anaglyph red cyan
        glDrawBuffer(GL_BACK);
        glGetIntegerv(GL_VIEWPORT, vp);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);

        // set camera for blue eye, red will be filtered.

        // draw scene
        glPushMatrix();
        glViewport(0, 0, ww, wh);        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glRotateL(1.5*minus,0,1,0);
        if (!pause) draw();
        glPopMatrix();
        glPopMatrix();

        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glClear(GL_DEPTH_BUFFER_BIT);
        glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);

        // set camera for red eye, blue will be filtered.

        // draw scene
        glPushMatrix();
        glViewport(0, 0, ww, wh);        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glRotateL(-1.5*minus,0,1,0);
        if (!pause) draw();
        glPopMatrix();
        glPopMatrix();
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

      }else  if (stereo_mode==5){//hardware stereo ???
        //todo  is this working??
        glGetIntegerv(GL_VIEWPORT, vp);

        //  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glPushMatrix();//2
        glViewport(0, 0, ww, wh);        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glRotateL(1.5*minus,0,1,0);
        glDrawBuffer(GL_BACK_RIGHT);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        if (!pause) draw();
        glPopMatrix();
        glPopMatrix();

        glPushMatrix();
        glViewport(0, 0, ww, wh);        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glRotateL(-1.5*minus,0,1,0);
        glDrawBuffer(GL_BACK_LEFT);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        if (!pause) draw();
        glPopMatrix();
        glPopMatrix();
      }
  {
    GLenum err = GL_NO_ERROR;
    while((err = glGetError()) != GL_NO_ERROR){      
      printf("paintGL %s err=%X\n",glError2String(err).toStdString().c_str(),err);
    }
  }
  //printf("%d pause%d\n",__LINE__,pause);  
}

void ChGL::setViewAngle(double ang){
  /*! sets ChGL.viewAngele for the perspective view 0 is othogonal, 29 degrees is the perpective default.
  */
  if ((ang>0.001)&&(ang<160.0)){
    printf("View angle = %g degrees. %10.8f %f\n",ang,ang/viewAngle,viewAngle);
    glScaled(ang/viewAngle,ang/viewAngle,ang/viewAngle);
    viewAngle=ang;
    homeXY();
  }
}

void ChGL::rehide(){//! Trys to hide previous hidden atoms.
  //printf("haa %d %d %g\n",hideReason,hiddenThings,qcutoff);
  if (!hiddenThings) return;
  if ((hideReason&HIDE_REASON_SELECT)&&(mol->selectedatoms.size())) {hideNonSelected(); return;}
  else if (hideReason&HIDE_REASON_SELECT) hideReason-=HIDE_REASON_SELECT;
  int gute=frid;
  for (int i=0;i<mol->showatoms.size();i++){
    if (hideReason&HIDE_REASON_QPEAK) if (mol->showatoms[i].an==-1) {if (qcutoff>0)
      mol->showatoms[i].hidden=((mol->showatoms[i].peakHeight>0)&&(mol->showatoms[i].peakHeight<qcutoff))?1:0;
      else mol->showatoms[i].hidden=((mol->showatoms[i].peakHeight<0)&&(mol->showatoms[i].peakHeight>qcutoff))?1:0;}
      if (hideReason&HIDE_REASON_HYDROGEN) mol->showatoms[i].hidden=
        (mol->showatoms.at(i).an==0)?1:mol->showatoms.at(i).hidden;
      if (hideReason&(HIDE_REASON_THIS_FRAGMENT|HIDE_REASON_OTHER_FRAGMENT)){
        if (mol->showatoms.at(i).an>=0){
          if (hideReason&HIDE_REASON_THIS_FRAGMENT) mol->showatoms[i].hidden=
            (mol->showatoms.at(i).molindex+withsymm*9999*mol->showatoms.at(i).symmGroup!=gute)?mol->showatoms.at(i).hidden:1;
          if (hideReason&HIDE_REASON_OTHER_FRAGMENT)mol->showatoms[i].hidden=
            (mol->showatoms.at(i).molindex+withsymm*9999*mol->showatoms.at(i).symmGroup!=gute)?1:mol->showatoms.at(i).hidden;
        }
      }
  }

}

void ChGL::hideNonSelected(){//! Hides all atoms that are not selected
  for (int i=0;i<mol->showatoms.size();i++) mol->showatoms[i].hidden=1;
  for(int i=0;i<mol->selectedatoms.size();i++){
    if (mol->selectedatoms.at(i).style < mol->showatoms.size())
      mol->showatoms[mol->selectedatoms.at(i).style].hidden=0;
    //   std::cout<<mol->showatoms.at(mol->selectedatoms.at(i).style).Label.toStdString()<<std::endl;
  }
  hiddenThings=true;
  hideReason|=HIDE_REASON_SELECT;
  mol->selectedatoms.clear();
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::hideSelected(){//! Hides the selected atoms
  for(int i=0;i<mol->selectedatoms.size();i++){
    if (mol->selectedatoms.at(i).style < mol->showatoms.size())
      mol->showatoms[mol->selectedatoms.at(i).style].hidden=1;
    //   std::cout<<mol->showatoms.at(mol->selectedatoms.at(i).style).Label.toStdString()<<std::endl;
  }
  hiddenThings=true;
  mol->selectedatoms.clear();
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::invertHidden(){//!< Toggle visibility of atoms etc
  if (!hiddenThings) return; // nothing is hidden => hide everything now? NO!
  for (int i=0;i<mol->legendAtoms.size();i++) mol->legendAtoms[i].hidden=1;
  QHash<int,bool> anExists;
  for (int i = 0; i < mol->showatoms.size(); i++){
    mol->showatoms[i].hidden = (mol->showatoms.at(i).hidden!=0)?0:1;
    if (!mol->showatoms.at(i).hidden) anExists[mol->showatoms.at(i).an]=true;
  } 
  for (int i=0;i<mol->legendAtoms.size();i++) if (anExists.contains(mol->legendAtoms.at(i).an)) mol->legendAtoms[i].hidden=0;
  frid=-10;
  hideReason=0;
  mol->selectedatoms.clear();
  murx=__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::sdm(){
    if (mol->asymm.size()<=SDM_Limit)return;//sdm is done regularly if number is below so we do not have to do iot now.
  if (!(fuse->isVisible()||grow->isVisible ())){
    fuse->setVisible(true);
    grow->setVisible(false);
  }
  mol->showatoms.clear();
  mol->showbonds.clear();
  mol->showatoms.clear();
  mol->showbonds.clear();
  mol->selectedatoms.clear();
  for (int o=0; o<mol->asymm.size();o++)
    mol->showatoms.append(mol->asymm[o]);
  mol->packer(mol->sdmcompleter());
  mol->showbonds =
    mol->connecting(mol->showatoms);
  mol->selectedatoms.clear();
  murx=__LINE__;
  bool growYes=fuse->isVisible ();
  mol->fuse();
  if (growYes) mol->grow();
  pause=false;
//  printf("%d\n",__LINE__);
  updateBondActions();
  updateGL();
}


void ChGL::hideThisFragment(){//! Hides the specified molecular fragment.
  sdm();
  QAction *action = qobject_cast<QAction *>(sender());
  int index=0;
  if (action)
    index=action->data().toInt();
  else return;
  if (index>mol->showatoms.size()) return;
  int gute=mol->showatoms.at(index).molindex+9999*mol->showatoms.at(index).symmGroup;
  //int gute=mol->showatoms.at(index).molindex;
  for (int i=0;i<mol->showatoms.size();i++) 
    if (mol->showatoms.at(i).an>=0)
      mol->showatoms[i].hidden=
        (mol->showatoms.at(i).molindex+9999*mol->showatoms.at(i).symmGroup!=gute)?mol->showatoms.at(i).hidden:1;
  //(mol->showatoms.at(i).molindex!=gute)?mol->showatoms.at(i).hidden:1;
  //
  frid=gute;
  hiddenThings=true;
  hideReason|=HIDE_REASON_THIS_FRAGMENT;
  mol->selectedatoms.clear();
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::selectThisFragment(){//! Selects the specified molecular fragment    
  sdm();
  QAction *action = qobject_cast<QAction *>(sender());
  int index=0;
  if (action)
    index=action->data().toInt();
  else return;
  if (index>mol->showatoms.size()) return;
  mol->selectedatoms.clear();
  int gute=mol->showatoms.at(index).molindex+9999*mol->showatoms.at(index).symmGroup;
  //int gute=mol->showatoms.at(index).molindex;
  for (int i=0;i<mol->showatoms.size();i++) 
    if (mol->showatoms.at(i).an>=0)
      if(mol->showatoms.at(i).molindex+9999*mol->showatoms.at(i).symmGroup==gute){
        mol->selectedatoms.append(mol->showatoms[i]);
        mol->selectedatoms.last().style=i;
      }
  //(mol->showatoms.at(i).molindex!=gute)?mol->showatoms.at(i).hidden:1;
  //
  updateBondActions();
  updateGL();
}

void ChGL::hideHydrogens(){//! Hides all Hydrogran atoms
  for (int i=0;i<mol->showatoms.size();i++) mol->showatoms[i].hidden=
    (mol->showatoms.at(i).an==0)?1:mol->showatoms.at(i).hidden;
  for (int i=0;i<mol->legendAtoms.size();i++) mol->legendAtoms[i].hidden=
      (mol->legendAtoms.at(i).an==0)?1:mol->legendAtoms.at(i).hidden;
  hiddenThings=true;
  hideReason|=HIDE_REASON_HYDROGEN;
  hideh->setVisible(false);
  mol->selectedatoms.clear();
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::wuff(){
  bool beloff=hideBeLo->isChecked();
  for (int i=0;i<mol->showatoms.size();i++) if (mol->showatoms.at(i).an==-42) mol->showatoms[i].hidden=(beloff)?0:1;
  for (int i=0;i<mol->legendAtoms.size();i++) if (mol->legendAtoms.at(i).an==-42) mol->legendAtoms[i].hidden=(beloff)?0:1;
  hiddenThings=hiddenThings||(!hideBeLo->isChecked());
  hideReason|=HIDE_REASON_BELO;
  //  hideh->setVisible(false);
  mol->selectedatoms.clear();
  murx=-__LINE__;
  updateBondActions();
  updateGL();

}

void ChGL::farbverlauf(double wrt, double min, double max){
    if (min>=max) max=min+0.001;
    double rot,gruen,blau,alpha;
    int lauf=0;
    const float farbe[6][4]={{1.0f,0.0f,0.0f,1.0f},
                          {1.0f,1.0f,0.0f,1.0f},
                          {0.0f,1.0f,0.0f,1.0f},
                          {0.0f,1.0f,1.0f,1.0f},
                          {0.0f,0.0f,1.0f,1.0f},
                          {1.0f,0.0f,1.0f,1.0f}};
    double nwrt=(wrt-min)/(max-min);
    nwrt=(nwrt>=1.0)?0.99999:nwrt;
    nwrt=(nwrt<=0.0)?0.00001:nwrt;
    lauf=(int (nwrt/0.2));
    nwrt-=(0.2*lauf);
    nwrt/=(0.2);

    rot=(((1.0-nwrt)*farbe[lauf][0]+farbe[lauf+1][0]*nwrt));
    gruen=(((1.0-nwrt)*farbe[lauf][1]+farbe[lauf+1][1]*nwrt));
    blau=(((1.0-nwrt)*farbe[lauf][2]+farbe[lauf+1][2]*nwrt));
    alpha=1.0;
    glColor4d(rot,gruen,blau,alpha);
}

QColor ChGL::farbverlaufQC(double wrt, double min, double max){
    if (min>=max) max=min+0.001;
    double rot,gruen,blau,alpha;
    int lauf=0;
    double farbe[6][4]={{1.0,0.0,0.0,1.0},
                       {1.0,1.0,0.0,1.0},
                          {0.0,1.0,0.0,1.0},
                          {0.0,1.0,1.0,1.0},
                          {0.0,0.0,1.0,1.0},
                          {1.0,0.0,1.0,1.0}};
    double nwrt=(wrt-min)/(max-min);
    nwrt=(nwrt>=1.0)?0.99999:nwrt;
    nwrt=(nwrt<=0.0)?0.00001:nwrt;
    lauf=(int (nwrt/0.2));
    nwrt-=(0.2*lauf);
    nwrt/=(0.2);

    rot=(((1.0-nwrt)*farbe[lauf][0]+farbe[lauf+1][0]*nwrt));
    gruen=(((1.0-nwrt)*farbe[lauf][1]+farbe[lauf+1][1]*nwrt));
    blau=(((1.0-nwrt)*farbe[lauf][2]+farbe[lauf+1][2]*nwrt));
    alpha=1.0;
    return QColor(static_cast<int>(255*rot),
           static_cast<int>(255*gruen),
           static_cast<int>(255*blau),
           static_cast<int>(255*alpha));
}


void ChGL::toogleWithSymmetry(bool b){
  withsymm=(b)?0:1;
}

void ChGL::hideOtherFragments(){//! Hides all molecular fragments except from the specified one    
  sdm();
  QAction *action = qobject_cast<QAction *>(sender());
  int index=0;
  if (action)
    index=action->data().toInt();
  else return;
  if (index==(int)((GLuint)-1))return;
  if (index>mol->showatoms.size()) return;
  int gute=mol->showatoms.at(index).molindex+withsymm*9999*mol->showatoms.at(index).symmGroup;
  //int gute=mol->showatoms.at(index).molindex;
  //  printf("hide %d %d %d \n",withsymm,gute,mol->showatoms.at(index).molindex+9999*mol->showatoms.at(index).symmGroup);
  for (int i=0;i<mol->showatoms.size();i++) 
    if (mol->showatoms.at(i).an>=0){
      mol->showatoms[i].hidden=
        //		(mol->showatoms.at(i).molindex!=gute)?1:mol->showatoms.at(i).hidden;
        (mol->showatoms.at(i).molindex+withsymm*9999*mol->showatoms.at(i).symmGroup!=gute)?1:mol->showatoms.at(i).hidden;
      //   printf("%d %d \n",mol->showatoms[i].hidden,mol->showatoms.at(i).molindex+withsymm*9999*mol->showatoms.at(i).symmGroup);
    }
  hiddenThings=true;
  frid=gute;
  hideReason|=HIDE_REASON_OTHER_FRAGMENT;
  mol->selectedatoms.clear();
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::highliteQPeak(double co){//! highligts the first Q-Peak with a lower or equal peak height than co. @param co cutoff value.
  imFokus=-1;
  //printf("co %f\n",co)
  for (int i=0;i<mol->showatoms.size();i++){
    if (mol->showatoms[i].an==-66) continue;
    if (mol->showatoms[i].an>=0) continue;
    if (mol->showatoms[i].hidden)continue;
    if (mol->showatoms[i].peakHeight<=co) {imFokus=i; break;}
  }
  updateGL();
}

void ChGL::hideQPeaksBelow(double cutoff){//!hides all Q-Peaks below the given cutoff value. @param cutoff The cutoff value.
  // qDebug()<<cutoff;
  int vor=0,nach=0;
  for (int i=0;i<mol->showatoms.size();i++){
    vor += mol->showatoms[i].hidden;
    if ((mol->showatoms[i].an == -1)&&(cutoff>0)) mol->showatoms[i].hidden = ((mol->showatoms[i].peakHeight>=0)&&(mol->showatoms[i].peakHeight<cutoff))?1:0;
    else if ((mol->showatoms[i].an ==-1)&&(cutoff<0)) mol->showatoms[i].hidden = ((mol->showatoms[i].peakHeight<=0)&&(mol->showatoms[i].peakHeight>cutoff))?1:0;
    //    if (mol->showatoms[i].an < 0) printf("#%d %g %d\n",mol->showatoms[i].hidden,mol->showatoms[i].peakHeight,mol->showatoms[i].peakHeight<cutoff);
    //    if (mol->showatoms[i].an == -66) mol->showatoms[i].hidden = 0;
    //    if (mol->showatoms[i].an == -42) mol->showatoms[i].hidden = 0;
    //  if (mol->showatoms[i].an < 0) printf("!%d %g %d\n",mol->showatoms[i].hidden,mol->showatoms[i].peakHeight,mol->showatoms[i].peakHeight<cutoff);
    nach += mol->showatoms[i].hidden;
  }
  for (int i=0;i<mol->legendAtoms.size();i++){
    if ((mol->legendAtoms[i].an == -1)&&(cutoff>0)) mol->legendAtoms[i].hidden = ((mol->legendAtoms[i].peakHeight>=0)&&(mol->legendAtoms[i].peakHeight<cutoff))?1:0;
    else if ((mol->legendAtoms[i].an ==-1)&&(cutoff<0)) mol->legendAtoms[i].hidden = ((mol->legendAtoms[i].peakHeight<=0)&&(mol->legendAtoms[i].peakHeight>cutoff))?1:0;
    //    if (mol->legendAtoms[i].an == -66) mol->legendAtoms[i].hidden = 0;
    //    if (mol->legendAtoms[i].an == -42) mol->legendAtoms[i].hidden = 0;
  }
  if (vor==nach) return;  
  hiddenThings=true;
  hideReason|=HIDE_REASON_QPEAK;
  qcutoff=cutoff;
  mol->selectedatoms.clear();
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::showHidden(){//! shows all hidden objects.
  int h=0;
  for (int i=0;i<mol->showatoms.size();i++){
    mol->showatoms[i].hidden=0;
    if (mol->showatoms[i].an==0)h++;
  }
  for (int i=0;i<mol->legendAtoms.size();i++){
    mol->legendAtoms[i].hidden=0;
    if (mol->legendAtoms[i].an==0)h++;
  }
  if (h)
    hideh->setVisible(true);
  hiddenThings=false;
  hideBeLo->setChecked(true);//toggle state is OK this way
  wuff();
  hideReason=0;
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::hidePartMinusOne(bool off){//! toggles the visibility state of part -N ghost atoms @param off if true no ghosts are visible.

  mol->nopm1=off;
  murx=-__LINE__;
  updateBondActions();
  updateGL();
}

void ChGL::setupTexture(){//!loads the texture images
  deleteTexture(mol->adpwall);
  deleteTexture(mol->adpwall_plaid);
  deleteTexture(mol->hbtex);

  mol->adpwall_plaid=bindTexture(QImage(QString(":/xle-icons/adpwall.png")),GL_TEXTURE_2D);
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  glBindTexture(GL_TEXTURE_2D, 0);

  mol->adpwall=bindTexture(QImage(QString(":/xle-icons/adpwall3.png")),GL_TEXTURE_2D);
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  glBindTexture(GL_TEXTURE_2D, 0);

  mol->hbtex=bindTexture(QImage(QString(":/xle-icons/hbb.png")),GL_TEXTURE_2D);
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  glBindTexture(GL_TEXTURE_2D, 0);

  //  mol->elitex=bindTexture(QImage(QString(":/xle-icons/eli.png")),GL_TEXTURE_2D);
  //  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  //  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  //  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  //  glBindTexture(GL_TEXTURE_2D, 0);
  //  printf("texture %d %d \n",mol->elitex,mol->hbtex);
}

void ChGL::homeXY(){//! Resets the molecule to rotate in the middle of the viewport.
  glGetDoublev(GL_MODELVIEW_MATRIX,MM);
  MM[12]=MM[13]=0;
  glLoadMatrixd(MM);
  updateGL();
}

void ChGL::draw(){//! draws everything some times by calling display lists.
  //printf("draw %d pause%d\n",__LINE__,pause);
  if (murx) {
    rehide();
    //printf("draw->murx %d %d \n",murx,mol->monoQrom);
    murx=0;

  }
  glCullFace(GL_BACK);
  glEnable(GL_DEPTH_TEST );
  QFontMetrics fmtr(myFont);
  nonAtomFont = myFont;
  nonAtomFont.setPointSize(qMax(((myFont.pointSize()*2)/3),7));
  QFontMetrics fmtr2(nonAtomFont);
  if (exporting) LabelZ.clear();
  const GLfloat  OBJ_SPE[]   = { 0.8f, 0.8f, 0.8f, 1.0f };
  const GLfloat  OBJ_SHIN    = 32.0f;
  glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR,             OBJ_SPE  );
  glEnable     ( GL_COLOR_MATERIAL ) ;
  glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;    
  glMaterialf(  GL_FRONT_AND_BACK, GL_SHININESS,           OBJ_SHIN );
  V3 ori=V3(0,0,0);///rotation origin
  V3 sumse=V3(0,0,0);
  int zz=0;
  objCnt=0;
  if (mol->showatoms.size()){
    for (int i=0;i<mol->showatoms.size();i++){
      if (!mol->showatoms[i].hidden) objCnt++;
      if ((!mol->showatoms.at(i).hidden)) {//(mol->showatoms.at(i).an>-1)&&
        sumse+=mol->showatoms[i].pos;
        zz++;
      }
    }

    if (zz) sumse*=1.0/zz;
    else {
      for (int i=0;i<mol->showatoms.size();i++){
        if (!mol->showatoms.at(i).hidden) {
          sumse+=mol->showatoms[i].pos;
          zz++;
        }
      }
      if (zz) sumse*=1.0/zz;
    }
  }
  //  printf(" zz %d %d \n",zz,mol->showatoms.size());
  glGetDoublev( GL_MODELVIEW_MATRIX, (double*)MM );
  double gmat[16];
  glGetDoublev( GL_MODELVIEW_MATRIX, (double*)gmat );
  ori.x=gmat[0] * sumse.x + gmat[4] * sumse.y + gmat[8] * sumse.z;
  ori.y=gmat[1] * sumse.x + gmat[5] * sumse.y + gmat[9] * sumse.z;
  ori.z=gmat[2] * sumse.x + gmat[6] * sumse.y + gmat[10] * sumse.z;
  if (mol->showatoms.size()<=rotze){
    rotze=-1;
    rCenter->hide();
  }
  if (rotze>-1) {
    double gmat[16];
    sumse=mol->showatoms.at(rotze).pos;
    glGetDoublev( GL_MODELVIEW_MATRIX, (double*)gmat );
    ori.x=gmat[0] * mol->showatoms.at(rotze).pos.x + gmat[4] * mol->showatoms.at(rotze).pos.y + gmat[8] *  mol->showatoms.at(rotze).pos.z;
    ori.y=gmat[1] * mol->showatoms.at(rotze).pos.x + gmat[5] * mol->showatoms.at(rotze).pos.y + gmat[9] *  mol->showatoms.at(rotze).pos.z;
    ori.z=gmat[2] * mol->showatoms.at(rotze).pos.x + gmat[6] * mol->showatoms.at(rotze).pos.y + gmat[10] * mol->showatoms.at(rotze).pos.z;
  }
  if (centerSelection->isChecked()){
    if (mol->selectedatoms.isEmpty()) {
      sumse=altemitte;//centerSelection->setChecked(false);
      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)gmat );
      ori.x=gmat[0] * sumse.x + gmat[4] * sumse.y + gmat[8] * sumse.z;
      ori.y=gmat[1] * sumse.x + gmat[5] * sumse.y + gmat[9] * sumse.z;
      ori.z=gmat[2] * sumse.x + gmat[6] * sumse.y + gmat[10] * sumse.z;
    }
    else {
      sumse=V3(0,0,0);
      for (int i=0;i<mol->selectedatoms.size();i++)
        sumse+=mol->selectedatoms[i].pos;
      sumse*=1.0/mol->selectedatoms.size();
      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)gmat );
      ori.x=gmat[0] * sumse.x + gmat[4] * sumse.y + gmat[8] * sumse.z;
      ori.y=gmat[1] * sumse.x + gmat[5] * sumse.y + gmat[9] * sumse.z;
      ori.z=gmat[2] * sumse.x + gmat[6] * sumse.y + gmat[10] * sumse.z;


    }
  }
  glPushMatrix();
  double mat[16];
  glEnable(GL_BLEND);
  glEnable(GL_COLOR_MATERIAL);
  glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mat );
  glLoadIdentity();
  glDisable( GL_LIGHTING ); 
  glDisable( GL_DEPTH_TEST ); 
  if ((bggradient)&&(!depthcueing)) {
    glPushMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective_( 29, (double)ww/wh, 5.0, 8000.0 );
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glBegin(GL_QUADS);
    double xx = ((double) ww / wh) * 2.0,
           yy = 1.77777777778;
    glColor4f(1.0f,1.0f,1.0f,0.5f);
    //glTexCoord2d(-1,-1);
    glVertex3d(-xx,-yy,-6.0);
    glColor4f(1.0f,1.0f,1.0f,0.5f);
    //glTexCoord2d(0,-1);
    glVertex3f( xx,-yy,-6.0);
    //glTexCoord2d(0,0);
    glColor4f(0.3f,0.3f,0.3f,0.7f);
    glVertex3d( xx, yy,-6.0);
    glColor4f(0.3f,0.3f,0.3f,0.7f);
    //glTexCoord2d(-1,0);
    glVertex3d(-xx, yy,-6.0);
    glEnd();

    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
  }  
  if (rectangle){
    glPushMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0,ww,0.0,wh,-1.0,1.0);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    glEnable(GL_LINE_STIPPLE);
    glEnable(GL_BLEND);
    glLineWidth(0.3f);
    glDisable(GL_LIGHTING);
    glLineStipple(3,21845);
    glBegin(GL_LINE_STRIP);
    qglColor(labelColor);
    glVertex3f(scrx0,wh-scry0,0.0f);
    glVertex3f(scrx,wh-scry0,0.0f);
    glVertex3f(scrx,wh-scry,0.0f);
    glVertex3f(scrx0,wh-scry,0.0f);
    glVertex3f(scrx0,wh-scry0,0.0f);
    glEnd();
    glDisable(GL_LINE_STIPPLE);
    glDisable(GL_BLEND);
    glEnable(GL_LIGHTING);
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
  }
  glEnable( GL_LIGHTING ); 
  glEnable( GL_DEPTH_TEST ); 
  if (depthcueing){
      glEnable(GL_FOG);
  }else{
      glDisable(GL_FOG);
  }

  glLoadMatrixd(mat);
  glPopMatrix();
  glPushMatrix();
  if ((!(sumse==V3(0,0,0)))&&(Distance(altemitte,sumse)>0.2)){
    //printf("neuemitte %f %f %f %f %f %f\n",sumse.x,sumse.y,sumse.z,altemitte.x,altemitte.y,altemitte.z);
    if(!(altemitte==V3(0,0,0))) emit neuemitte(altemitte);
    altemitte=sumse;
  }
  if (rotze==-76185){
    glGetDoublev( GL_MODELVIEW_MATRIX, (double*)gmat );
    ori.x=gmat[0] * altcenter.x + gmat[4] * altcenter.y + gmat[8] *  altcenter.z;
    ori.y=gmat[1] * altcenter.x + gmat[5] * altcenter.y + gmat[9] *  altcenter.z;
    ori.z=gmat[2] * altcenter.x + gmat[6] * altcenter.y + gmat[10] * altcenter.z;
  }
  glTranslateL(-L*ori.x,-L*ori.y,-L*ori.z);

  glPushMatrix();{
    glScaled( L, L, L );
    if ((wireButt->isChecked())&&(moving->isActive())) {
      mol->dratom=5;
      mol->intern=0;
      mol->adp=(drawADP)?1:0;
      mol->dbond(mol->showbonds);
      mol->atoms(mol->showatoms,mol->proba);
      mol->lbond();
    }
    else {
      if (!apair.isEmpty()){
        mol->dbond(apair);
      }
      if (drawHb)  {
        mol->tubes=(tubes&&!drawADP)?1:0;
        mol->adp=(drawADP)?1:0;
        mol->h_bonds2(mol->showbonds,mol->showatoms);

      }
      //     printf("qPeakBonds %d !%d\n",mol->lbonds.size(),mol->showatoms.size());
      if (qPeakBonds->isChecked())mol->lbond();//bonds
      if (drawAt) {
        mol->intern=1;
        mol->adp=(drawADP)?1:0;
        mol->tubes=(tubes&&!drawADP)?1:0;
        mol->atoms(mol->showatoms,mol->proba);
        if (drawADP&&(!mol->useShaders)) {
          mol->intern=0;
          mol->atoms(mol->showatoms,mol->proba);
        }        

      }

      if (drawBo) {
        if (mol->bondColorStyle){
          qglColor(mol->bondColor);
          glDisable(GL_COLOR_MATERIAL);
        }
        mol->adp=(drawADP)?1:0;
        mol->tubes=(tubes)?1:0;
        glEnable(GL_CULL_FACE);
        glCullFace(GL_FRONT);
        mol->bonds(mol->showbonds);
        glDisable(GL_CULL_FACE);
        glCullFace(GL_BACK);

        glEnable(GL_COLOR_MATERIAL);
      }
    }//wireButt
  }glPopMatrix();

  if ((!habzutun)&&(!fVertexes[0].isEmpty()||!fVertexes[1].isEmpty())) {
      //printf("maps\n");
    double max;
    int Pers=0;
    if (niceTrans->isChecked()){
      double mm[16];

      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mm );
      max= (fabs(mm[2])>fabs(mm[6]))?mm[2]:mm[6];
      max=(fabs(max)<fabs(mm[10]))?mm[10]:max;
      if ((max==mm[2])&&(max>0.0)) Pers=0; else
        if ((max==mm[2])&&(max<0.0)) Pers=1; else
          if ((max==mm[6])&&(max>0.0)) Pers=2; else
            if ((max==mm[6])&&(max<0.0)) Pers=3; else
              if ((max==mm[10])&&(max>0.0)) Pers=4; else
                if ((max==mm[10])&&(max<0.0)) Pers=5;
    }else Pers=0;
    glDisable(GL_CULL_FACE);
    if (fillMap->isChecked()) glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    else glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    if (lighting->isChecked())  glEnable(GL_LIGHTING); 
    else glDisable(GL_LIGHTING);
    glEnable(GL_BLEND);
    glLineWidth(linwidth);

    glPushMatrix();
    glScaled( L, L, L);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    if (fofcact->isChecked()) {
      dipc.setAlphaF(lintrans);
      qglColor(dipc);
      glVertexPointer(3, GL_FLOAT, 0, fVertexes[0+4*Pers].data());
      glNormalPointer(GL_FLOAT, 0, fNormals[0+4*Pers].data());
      glDrawArrays(GL_TRIANGLES, 0, fVertexes[0+4*Pers].size()/3);
      dimc.setAlphaF(lintrans);
      qglColor(dimc);
      glVertexPointer(3, GL_FLOAT, 0, fVertexes[1+4*Pers].data());
      glNormalPointer(GL_FLOAT, 0, fNormals[1+4*Pers].data());
      glDrawArrays(GL_TRIANGLES, 0, fVertexes[1+4*Pers].size()/3);
    }
    if (foact->isChecked()) {
      fopc.setAlphaF(lintrans);
      qglColor(fopc);
      glVertexPointer(3, GL_FLOAT, 0, fVertexes[2+4*Pers].data());
      glNormalPointer(GL_FLOAT, 0, fNormals[2+4*Pers].data());
      glDrawArrays(GL_TRIANGLES, 0, fVertexes[2+4*Pers].size()/3);
      if (neutrons){
        fomc.setAlphaF(lintrans);
        qglColor(fomc);
        glVertexPointer(3, GL_FLOAT, 0, fVertexes[3+4*Pers].data());
        glNormalPointer(GL_FLOAT, 0, fNormals[3+4*Pers].data());
        glDrawArrays(GL_TRIANGLES, 0, fVertexes[3+4*Pers].size()/3);
      }
    }
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glPopMatrix();

    glEnable(GL_LIGHTING);
    glDisable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  }

  if (!mol->selectedatoms.isEmpty()){
    glPushMatrix();{
      glLineWidth(2);
      glScaled( L, L, L );
      mol->tubes=0;
      mol->intern=1;
      mol->adp=0;
      mol->dratom=1;
      mol->atoms(mol->selectedatoms);
      qglColor(labelColor);
      mol->dratom=0;
      glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
      mol->intern=1;
      mol->tubes=0;
      mol->adp=1;
    }glPopMatrix();
  }

  if (!mol->fitbonds.isEmpty()){
    glPushMatrix();{
      glLineWidth(1);
      glScaled( L, L, L );
      mol->tubes=0;
      mol->intern=1;
      mol->adp=0;
      mol->dratom=76;
      mol->atoms(mol->fitatoms);
      mol->dbond(mol->fitbonds,76);
      qglColor(labelColor);
      mol->dratom=0;
      glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
      mol->intern=1;
      mol->tubes=0;
      mol->adp=1;
    }glPopMatrix();
  }
  if (highlightParts->isChecked()){//PART highlighter
    glPushMatrix();{
      glScaled( L, L, L );
      mol->tubes=(tubes&&!drawADP)?1:0;
      mol->intern=0;
      mol->adp=(drawADP)?1:0;
      mol->dratom=2;
      mol->atoms(mol->showatoms);
      qglColor(labelColor);
    }glPopMatrix();
    glPushMatrix();{
      glDisable(GL_CULL_FACE);
      glScaled( L, L, L );
      mol->bonds(mol->showbonds);
      glEnable(GL_CULL_FACE);
    }glPopMatrix();
    mol->dratom=0;
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  }
  if (mol->duplicateAtoms.size()){//Duplicate highlighter
    glPushMatrix();{
      glScaled( L, L, L );
      mol->tubes=(tubes&&!drawADP)?1:0;
      mol->intern=0;
      mol->adp=(drawADP)?1:0;
      mol->dratom=2;
      mol->atoms(mol->duplicateAtoms);

      qglColor(QColor("springgreen"));
      glDisable(GL_DEPTH_TEST);
      if (stereo_mode!=1)
        for (int ii=0; ii<mol->duplicateAtoms.size();ii++)renderText(
            mol->duplicateAtoms.at(ii).pos.x,
            mol->duplicateAtoms.at(ii).pos.y,
            mol->duplicateAtoms.at(ii).pos.z,
            "="+mol->duplicateAtoms.at(ii).Label+"=",
            myFont);

      qglColor(labelColor);
    }glPopMatrix();  
    mol->dratom=0;
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  }
  if ((imFokus>-1)&&(!drawLa)&&(imFokus<mol->showatoms.size()))
    if (!warLabel){
      CEnvironment fokat;
      fokat.append(mol->showatoms.at(imFokus));
      glPushMatrix();{
        glScaled( L, L, L );
        mol->tubes=0;
        mol->intern=1;
        mol->adp=0;
        mol->dratom=3;
        mol->atoms(fokat);
        qglColor(labelColor);
        mol->dratom=0;
        glDisable(GL_DEPTH_TEST);
        if ((stereo_mode!=1)&&(!useTextureLabels->isChecked()))renderText(
            fokat.at(0).pos.x,
            fokat.at(0).pos.y,
            fokat.at(0).pos.z, 
            fokat.at(0).Label,
            myFont);
        glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
        glEnable(GL_DEPTH_TEST);
      }glPopMatrix();
      ///
      if (useTextureLabels->isChecked()){
        glPushMatrix();
        glScaled(L,L,L);
        if (!mol->showatoms.isEmpty()){
          if (mol->showatoms.size()!=labelTextures.size()) updateLabelTextures();
          glDisable(GL_CULL_FACE);
          glDisable(GL_DEPTH_TEST);

          glEnable(GL_BLEND);
          glEnable(GL_ALPHA_TEST);

          glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
          glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
          glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
          glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
          glEnable(GL_TEXTURE_2D);

          bool bigr=false;
          qglColor(labelColor);
          glPushMatrix();
          GLdouble mmm[16];
          GLuint t=bindTexture(labelTextures.at(imFokus),GL_TEXTURE_2D);
          double ratio=(double)labelTextures.at(imFokus).width()/labelTextures.at(imFokus).height();
          glTranslated(mol->showatoms.at(imFokus).pos.x,mol->showatoms.at(imFokus).pos.y,mol->showatoms.at(imFokus).pos.z);
          glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mmm);
          double ddd = mmm[0] * (mmm[5] * mmm[10] - mmm[9] * mmm[6])
            - mmm[1] * (mmm[4] * mmm[10] - mmm[8] * mmm[6])
            + mmm[2] * (mmm[4] *  mmm[9] - mmm[8] * mmm[5]);
          ddd=pow(ddd,1.0/3.0);
          ddd*=(mol->showatoms.at(imFokus).an>=0)?1.0:0.75;
          ddd*=(bigr)?1.2:1.0;
          mmm[0]=ddd*labScal*ratio;
          mmm[5]=ddd*labScal;
          mmm[10]=ddd*labScal;
          mmm[1]=mmm[2]=mmm[4]=mmm[6]=mmm[8]=mmm[9]=0.0;
          glLoadMatrixd(mmm);
          mol->billBoard();
          glPopMatrix();
          deleteTexture(t);
        }
        glPopMatrix();
      }
      ///

    }

  if (enviPositions.size()){
    glPushMatrix();
    glDisable( GL_DEPTH_TEST );
    glEnable(GL_LINE_STIPPLE);
    glEnable(GL_BLEND);
    glLineWidth(2);
    glDisable(GL_LIGHTING);
    glLineStipple(3,21845);

    glScaled( L, L, L );
    glBegin(GL_LINES);
    for (int k=0;k<enviPositions.size();k++){
      if ((enviNoQ->isChecked())&&(labs.at(k).startsWith('Q',Qt::CaseInsensitive))) continue;
      switch(enviKat.at(k)){
        case 1: qglColor(mol->enviBondColor);break;
        case 2: qglColor(mol->enviHBColor);break;
        default:
                qglColor(mol->enviDefaultColor);
      }
      //if ((Distance(enviP0,enviPositions.at(k)))<envirange*envirange)
      {
        glVertex3d(enviP0.x,enviP0.y,enviP0.z);
        glVertex3d(enviPositions.at(k).x,enviPositions.at(k).y,enviPositions.at(k).z);
      }
    }
    glEnd();

    glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);


    glEnable(GL_BLEND);
    glEnable(GL_ALPHA_TEST);

    //glBindTexture(GL_TEXTURE_2D, t);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glEnable(GL_TEXTURE_2D);
    for (int k=0;k<enviPositions.size();k++){

      if ((enviNoQ->isChecked())&&(labs.at(k).startsWith('Q',Qt::CaseInsensitive))) continue;
      if ((k+labs.size()) >= enviTextures.size()) continue;
      switch(enviKat.at(k)){
        case 1: qglColor(mol->enviBondColor);break;
        case 2: qglColor(mol->enviHBColor);break;
        default:
                qglColor(mol->enviDefaultColor);
      }
      glPushMatrix();
      GLdouble mmm[16];

      GLuint t=bindTexture(enviTextures.at(k+labs.size()),GL_TEXTURE_2D);
      double ratio=(double)enviTextures.at(k+labs.size()).width()/enviTextures.at(k+labs.size()).height();
      glTranslated((enviPositions.at(k).x+enviP0.x)/2.0,
                   (enviPositions.at(k).y+enviP0.y)/2.0,
                   (enviPositions.at(k).z+enviP0.z)/2.0);
      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mmm);
      double ddd = mmm[0] * (mmm[5] * mmm[10] - mmm[9] * mmm[6])
        - mmm[1] * (mmm[4] * mmm[10] - mmm[8] * mmm[6])
        + mmm[2] * (mmm[4] *  mmm[9] - mmm[8] * mmm[5]);
      ddd=pow(ddd,1.0/3.0);
      mmm[0]=ddd*labScal*ratio;
      mmm[5]=ddd*labScal;
      mmm[10]=ddd*labScal;
      mmm[1]=mmm[2]=mmm[4]=mmm[6]=mmm[8]=mmm[9]=0.0;
      /*
         printf("\n\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\n",mmm[0]
         ,mmm[1],mmm[2],mmm[3]
         ,mmm[4],mmm[5],mmm[6],mmm[7]
         ,mmm[8],mmm[9],mmm[10],mmm[11]
         ,mmm[12],mmm[13],mmm[14],mmm[15]
         );
      // */
      glLoadMatrixd(mmm);
      mol->billBoard();
      deleteTexture(t+labs.size());
      glPopMatrix();
      glPushMatrix();
      t=bindTexture(enviTextures.at(k),GL_TEXTURE_2D);
      ratio=(double)enviTextures.at(k).width()/enviTextures.at(k).height();
      glTranslated(enviPositions.at(k).x,
                   enviPositions.at(k).y,
                   enviPositions.at(k).z);
      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mmm);
      ddd = mmm[0] * (mmm[5] * mmm[10] - mmm[9] * mmm[6])
        - mmm[1] * (mmm[4] * mmm[10] - mmm[8] * mmm[6])
        + mmm[2] * (mmm[4] *  mmm[9] - mmm[8] * mmm[5]);
      ddd=pow(ddd,1.0/3.0);
      mmm[0]=ddd*labScal*ratio;
      mmm[5]=ddd*labScal;
      mmm[10]=ddd*labScal;
      mmm[1]=mmm[2]=mmm[4]=mmm[6]=mmm[8]=mmm[9]=0.0;
      /*
         printf("\n\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\n",mmm[0]
         ,mmm[1],mmm[2],mmm[3]
         ,mmm[4],mmm[5],mmm[6],mmm[7]
         ,mmm[8],mmm[9],mmm[10],mmm[11]
         ,mmm[12],mmm[13],mmm[14],mmm[15]
         );
      // */
      glLoadMatrixd(mmm);
      mol->billBoard();
      glPopMatrix();
      deleteTexture(t);
      /*
      renderText((enviPositions.at(k).x+enviP0.x)/2.0,
          (enviPositions.at(k).y+enviP0.y)/2.0,
          (enviPositions.at(k).z+enviP0.z)/2.0,
          QString::number(sqrt(Distance(enviP0,enviPositions.at(k))),'f',3)+"Å",nonAtomFont);
      renderText(enviPositions.at(k).x,
          enviPositions.at(k).y,
          enviPositions.at(k).z,
          labs.at(k),nonAtomFont);
          */
    }
    glDisable(GL_LINE_STIPPLE);
    glEnable(GL_LIGHTING);
    glEnable( GL_DEPTH_TEST );
    glPopMatrix();
  }
  if (drawUc) {
    glPushMatrix();
    glScaled( L, L, L );
    mol->unitCell();
    glPopMatrix();
  }
  if ((!useTextureLabels->isChecked())&&(drawLa)&&(!moving->isActive())&&drawUc) {
    glClear( GL_DEPTH_BUFFER_BIT);
    V3 uz0f,uz1f,uz2f,uz3f;
    V3 uz0k,uz1k,uz2k,uz3k;
    uz0f.x=0.0;  uz0f.y=0.0;  uz0f.z=0.0;
    uz1f.x=1.0;  uz1f.y=0.0;  uz1f.z=0.0;
    uz2f.x=0.0;  uz2f.y=1.0;  uz2f.z=0.0;
    uz3f.x=0.0;  uz3f.y=0.0;  uz3f.z=1.0;
    mol->frac2kart(uz0f,uz0k);
    mol->frac2kart(uz1f,uz1k);
    mol->frac2kart(uz2f,uz2k);
    mol->frac2kart(uz3f,uz3k);
    glPushMatrix();{
      glScaled(L,L,L);{
        qglColor(labelColor);

        renderText(uz0k.x,uz0k.y,uz0k.z,"0",myFont);
        glColor4f(1.0f,0.0f,0.0f,1.0);
        renderText(uz1k.x,uz1k.y,uz1k.z,"a",myFont);

        glColor4f(0.0f,1.0f,0.0f,1.0);
        renderText(uz2k.x,uz2k.y,uz2k.z,"b",myFont);

        glColor4f(0.0f,0.0f,1.0f,1.0);
        renderText(uz3k.x,uz3k.y,uz3k.z,"c",myFont);
      }glPopMatrix();
    }
  }
  if ((useTextureLabels->isChecked())&&(drawLa)){
    glPushMatrix();
    glScaled(L,L,L);
    if (!mol->showatoms.isEmpty()){
      if (mol->showatoms.size()!=labelTextures.size()) updateLabelTextures();
      glDisable(GL_CULL_FACE);
      glDisable(GL_DEPTH_TEST);


      glEnable(GL_BLEND);
      glEnable(GL_ALPHA_TEST);

      //glBindTexture(GL_TEXTURE_2D, t);
      glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      glEnable(GL_TEXTURE_2D);
      for (int li=0; li<mol->showatoms.size();li++){
        if (mol->showatoms.at(li).hidden) continue;
        if ((mol->nopm1)&&(mol->showatoms.at(li).symmGroup)&&(mol->showatoms.at(li).part<-0)) continue;
        if ((mol->AtomStyle[mol->showatoms.at(li).an]&ATOM_STYLE_NOLABEL)&&(imFokus!=li)) continue;
        if ((!mol->beloLabels)&&(mol->showatoms.at(li).an==-42)) continue;
        bool bigr=false;
        qglColor(labelColor);
        for (int si=0; si<mol->selectedatoms.size(); si++){
          if (li==mol->selectedatoms.at(si).style) {qglColor(QColor("#3388FF"));bigr=true;}
        }
        if (imFokus==li) {bigr=true;qglColor(QColor("#FF9900"));}
        glPushMatrix();
        GLdouble mmm[16];
        GLuint t=bindTexture(labelTextures.at(li),GL_TEXTURE_2D);
        double ratio=(double)labelTextures.at(li).width()/labelTextures.at(li).height();
        glTranslated(mol->showatoms.at(li).pos.x,mol->showatoms.at(li).pos.y,mol->showatoms.at(li).pos.z);
        glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mmm);
        double ddd = mmm[0] * (mmm[5] * mmm[10] - mmm[9] * mmm[6])
          - mmm[1] * (mmm[4] * mmm[10] - mmm[8] * mmm[6])
          + mmm[2] * (mmm[4] *  mmm[9] - mmm[8] * mmm[5]);
        ddd=pow(ddd,1.0/3.0);
        ddd*=(mol->showatoms.at(li).an>=0)?1.0:0.75;
        ddd*=(bigr)?1.2:1.0;
        mmm[0]=ddd*labScal*ratio;
        mmm[5]=ddd*labScal;
        mmm[10]=ddd*labScal;
        mmm[1]=mmm[2]=mmm[4]=mmm[6]=mmm[8]=mmm[9]=0.0;
        /*
           printf("\n\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\n",mmm[0]
           ,mmm[1],mmm[2],mmm[3]
           ,mmm[4],mmm[5],mmm[6],mmm[7]
           ,mmm[8],mmm[9],mmm[10],mmm[11]
           ,mmm[12],mmm[13],mmm[14],mmm[15]
           );
        // */
        glLoadMatrixd(mmm);
        mol->billBoard();
        glPopMatrix();
        deleteTexture(t);
      }
      if (drawUc){
        V3 uz0f,uz1f,uz2f,uz3f;
        V3 uz0k,uz1k,uz2k,uz3k;
        uz0f.x=0.0;  uz0f.y=0.0;  uz0f.z=0.0;
        uz1f.x=1.0;  uz1f.y=0.0;  uz1f.z=0.0;
        uz2f.x=0.0;  uz2f.y=1.0;  uz2f.z=0.0;
        uz3f.x=0.0;  uz3f.y=0.0;  uz3f.z=1.0;
        mol->frac2kart(uz0f,uz0k);
        mol->frac2kart(uz1f,uz1k);
        mol->frac2kart(uz2f,uz2k);
        mol->frac2kart(uz3f,uz3k);
        for (int li=0; li<4; li++){
          glPushMatrix();
          GLdouble mmm[16];
          GLuint t=bindTexture(extraTextures.at(li),GL_TEXTURE_2D);
          double ratio=(double)extraTextures.at(li).width()/extraTextures.at(li).height();
          switch (li){
            case 0:
              qglColor(labelColor);
              glTranslated(uz0k.x,uz0k.y,uz0k.z);
              break;
            case 1:
              glColor4f(1.0f,0.0f,0.0f,1.0);
              glTranslated(uz1k.x,uz1k.y,uz1k.z);
              break;
            case 2:
              glColor4f(0.0f,1.0f,0.0f,1.0);
              glTranslated(uz2k.x,uz2k.y,uz2k.z);
              break;
            case 3:
              glColor4f(0.0f,0.0f,1.0f,1.0);
              glTranslated(uz3k.x,uz3k.y,uz3k.z);
              break;
          }
          glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mmm);
          double ddd = mmm[0] * (mmm[5] * mmm[10] - mmm[9] * mmm[6])
            - mmm[1] * (mmm[4] * mmm[10] - mmm[8] * mmm[6])
            + mmm[2] * (mmm[4] *  mmm[9] - mmm[8] * mmm[5]);
          ddd=pow(ddd,1.0/3.0);
          mmm[0]=ddd*labScal*ratio;
          mmm[5]=ddd*labScal;
          mmm[10]=ddd*labScal;
          mmm[1]=mmm[2]=mmm[4]=mmm[6]=mmm[8]=mmm[9]=0.0;
          /*
             printf("\n\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\nd%f %f %f %f\n",mmm[0]
             ,mmm[1],mmm[2],mmm[3]
             ,mmm[4],mmm[5],mmm[6],mmm[7]
             ,mmm[8],mmm[9],mmm[10],mmm[11]
             ,mmm[12],mmm[13],mmm[14],mmm[15]
             );
          // */
          glLoadMatrixd(mmm);
          mol->billBoard();
          glPopMatrix();
          deleteTexture(t);
        }
      }
      glDisable(GL_TEXTURE_2D);
      glEnable(GL_BLEND);
      glDisable(GL_ALPHA_TEST);
      glEnable(GL_DEPTH_TEST);
    }
    glPopMatrix();
  }
  if ((!useTextureLabels->isChecked())&&(drawLa)&&(!moving->isActive())) {


    glClear( GL_DEPTH_BUFFER_BIT);
    glPushMatrix();{
      glScaled(L,L,L);
      GLdouble model[16];
      GLdouble proj[16];
      GLint viewport[4];
      glGetIntegerv(GL_VIEWPORT, viewport);
     // printf("%d %d %d %d\n",viewport[0],viewport[1],viewport[2],viewport[3]);
      glGetDoublev( GL_PROJECTION_MATRIX , (double*)proj );
      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)model );
      {
        for (int j=0;j<mol->showatoms.size();j++){
          if ((!mol->beloLabels)&&(mol->showatoms.at(j).an==-42)) continue;
          if (mol->showatoms.at(j).hidden) continue;
          if ((mol->nopm1)&&(mol->showatoms.at(j).symmGroup)&&(mol->showatoms.at(j).part<-0)) continue;
          if (imFokus==j) qglColor(QColor("#FFAA00")); else {
            if ((mol->highlightEquivalents)&&(mol->showatoms.at(j).symmGroup)) {
              if ((backGroundColor.saturation()>128)&&(abs(backGroundColor.hue()-240)<30)) qglColor(Qt::lightGray);
              else {
                if (backGroundColor.value()<128) qglColor(QColor(Qt::blue).lighter(150));
                else qglColor(Qt::darkBlue);
              }
            }
            else qglColor(labelColor);
          }
          //{1.0,0.0,-1.0,-190},
          GLdouble in[4], out[4];

          in[0] = mol->showatoms.at(j).pos.x;
          in[1] = mol->showatoms.at(j).pos.y;
          in[2] = mol->showatoms.at(j).pos.z;
          in[3] = 1.0;
          transform_point(out, model, in);
          posTo2D(mol->showatoms.at(j).pos,model,proj,vp, &mol->showatoms[j].screenX, &mol->showatoms[j].screenY,retinafktr);
          int xminus = fmtr.boundingRect(mol->showatoms.at(j).Label).width();
          int x2minus = fmtr2.boundingRect(mol->showatoms.at(j).Label).width();
          int yminus = fmtr.boundingRect(mol->showatoms.at(j).Label).height();
          int y2minus = fmtr2.boundingRect(mol->showatoms.at(j).Label).height();
          int displace=10;
          int displace2=displace/2;
          if (exporting){
            double mult= (double)ww/width();
            displace*=mult;
            displace2*=mult;
            labz ll;
            ll.x=(mol->showatoms[j].screenX<ww/2)?
              mol->showatoms[j].screenX-(xminus+displace):
              mol->showatoms[j].screenX+displace;
            ll.y=(mol->showatoms[j].screenY<wh/2)?
              mol->showatoms[j].screenY-displace2:
              mol->showatoms[j].screenY+yminus;
            ll.l=mol->showatoms.at(j).Label;
            ll.an=mol->showatoms.at(j).an;
            LabelZ.append(ll);
          }
          else{
            if (imFokus==j) {
              renderText( 
                  (mol->showatoms[j].screenX<ww/2)?
                  mol->showatoms[j].screenX-(xminus+displace):
                  mol->showatoms[j].screenX+displace,
                  (mol->showatoms[j].screenY<wh/2)?
                  mol->showatoms[j].screenY-displace2:
                  mol->showatoms[j].screenY+yminus,
                  mol->showatoms.at(j).Label,
                  //nonAtomFont);
                myFont);
              continue;

            }else {
              if ((mol->showatoms.at(j).an<0)) renderText(//(mol->selectedatoms.isEmpty())&&
                  (mol->showatoms[j].screenX<ww/2)?
                  mol->showatoms[j].screenX-(x2minus+displace):
                  mol->showatoms[j].screenX+displace,
                  (mol->showatoms[j].screenY<wh/2)?
                  mol->showatoms[j].screenY-displace2:
                  mol->showatoms[j].screenY+y2minus,
                  mol->showatoms.at(j).Label,
                  nonAtomFont);
              else
                if ((!(mol->AtomStyle[mol->showatoms.at(j).an]&ATOM_STYLE_NOLABEL)))//(mol->selectedatoms.isEmpty())&&
                  renderText(
                      (mol->showatoms[j].screenX<ww/2)?
                      mol->showatoms[j].screenX-(((mol->selectedatoms.isEmpty())?xminus:x2minus)+displace):
                      mol->showatoms[j].screenX+displace,
                      (mol->showatoms[j].screenY<wh/2)?
                      mol->showatoms[j].screenY-displace2:
                      mol->showatoms[j].screenY+((mol->selectedatoms.isEmpty())?yminus:y2minus),
                      mol->showatoms.at(j).Label,
                      (mol->selectedatoms.isEmpty())?myFont:nonAtomFont);
            }
          }
        }
      }
      if (!exporting)for (int j=0;j<mol->selectedatoms.size();j++){
        int xminus = fmtr.boundingRect(mol->selectedatoms.at(j).Label).width();
        int yminus = fmtr.boundingRect(mol->selectedatoms.at(j).Label).height();
        int displace=10;
        int displace2=displace/2;
        GLdouble in[4], out[4];
        in[0] = mol->selectedatoms.at(j).pos.x;
        in[1] = mol->selectedatoms.at(j).pos.y;
        in[2] = mol->selectedatoms.at(j).pos.z;
        in[3] = 1.0;
        transform_point(out, model, in);
        posTo2D(mol->selectedatoms.at(j).pos,model,proj,viewport, &mol->selectedatoms[j].screenX, &mol->selectedatoms[j].screenY,retinafktr);
        //          int x2minus = fmtr2.boundingRect(mol->selectedatoms.at(j).Label).width();
        //          int y2minus = fmtr2.boundingRect(mol->selectedatoms.at(j).Label).height();
        qglColor(Qt::yellow);

        renderText(
            (mol->selectedatoms[j].screenX<ww/2)?
            mol->selectedatoms[j].screenX-((xminus)+displace):
            mol->selectedatoms[j].screenX+displace,
            (mol->selectedatoms[j].screenY<wh/2)?
            mol->selectedatoms[j].screenY-displace2:
            mol->selectedatoms[j].screenY+(yminus),
            mol->selectedatoms.at(j).Label,
            myFont);
      }
    }glPopMatrix();
  }  
  {
    glPushMatrix();
    glScaled(L,L,L);{
      GLdouble model[16];
      GLdouble proj[16];
      GLint viewport[4];
      glGetIntegerv(GL_VIEWPORT, viewport);
      glGetDoublev( GL_PROJECTION_MATRIX , (double*)proj );
      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)model );
      for (int j=0;j<mol->showatoms.size();j++){
        {mol->showatoms[j].screenX=-200; mol->showatoms[j].screenY=-200;}
        if (mol->showatoms.at(j).hidden) continue;
        //{1.0,0.0,-1.0,-190},
        GLdouble in[4], out[4];

        in[0] = mol->showatoms.at(j).pos.x;
        in[1] = mol->showatoms.at(j).pos.y;
        in[2] = mol->showatoms.at(j).pos.z;
        in[3] = 1.0;
        transform_point(out, model, in);

        if ((mol->nopm1)&&(mol->showatoms.at(j).symmGroup)&&(mol->showatoms.at(j).part<-0)) continue;
        if (!posTo2D(mol->showatoms.at(j).pos,model,proj,viewport, &mol->showatoms[j].screenX, &mol->showatoms[j].screenY,retinafktr))
        {mol->showatoms[j].screenX=-200; mol->showatoms[j].screenY=-200;}
      }
    }
    glPopMatrix();
  }
  glPopMatrix();

  V3 auge=V3(0,0,206);
  if (mol->vorobas){
    glPushMatrix();
    glDisable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glEnable(GL_ALPHA_TEST);

    glEnable( GL_LIGHTING );
    glTranslateL(-L*ori.x,-L*ori.y,-L*ori.z);
    glScaled( L, L, L );

    glGetDoublev( GL_MODELVIEW_MATRIX, (double*)gmat );
    Matrix mvm=Matrix(gmat[0],gmat[1],gmat[2], gmat[4],gmat[5],gmat[6], gmat[8],gmat[9],gmat[10]);
    auge=mvm*auge;
    mol->drawVoronoi(auge);
    glPopMatrix();

    glDisable( GL_LIGHTING );
  }
    if (!cont.isEmpty()){ 
      glPushMatrix();{
        glTranslateL(-L*ori.x,-L*ori.y,-L*ori.z);
        glScaled( L, L, L );
        glDisable( GL_LIGHTING ); 
        glEnable( GL_DEPTH_TEST );
        glLineWidth(2.5f);

        glBegin(GL_LINES);
        for (int ci=0;ci<cont.size();ci++){
          if (contval.contains(ci)) {
              if (rainbowPlot->isChecked()) farbverlauf(contval.value(ci),contMin,contMax);
              else{
                  if (contval.value(ci)>0.0001f) {
                      glColor4d(0.0,0.0,1.0,1.0);
                  } else if (contval.value(ci)<-0.0001f){
                      glColor4d(1.0,0.0,0.0,1.0);
                  } else {
                      glColor4d(0.0,0.0,0.0,1.0);
                  }
              }
          }
          glVertex3d(cont.at(ci).x,cont.at(ci).y,cont.at(ci).z);
        }
        glEnd();
        glEnable( GL_LIGHTING ); 
        //glEnable( GL_DEPTH_TEST ); 
      }glPopMatrix();
      glLineWidth(0.7f);
    }

  if (atomLegend->isChecked()){                
      glDisable(GL_FOG);
      mol->mist=false;
      for (int ali=0,alj=0; ali<mol->legendAtoms.size(); ali++){
          mol->legendAtoms[ali].pos.y=-6.8+alj*0.5;
          if (mol->legendAtoms.at(ali).hidden) continue;
          alj++;
      }
    glPushMatrix();{
      GLsizei  lw=415;
      GLsizei  lh=950;
      //printf("legend %d %d\n",lw,lh);
      glViewport(0, 0, lw, lh);
      double mat[16],mleg[16];
      glEnable(GL_BLEND);
      glEnable(GL_COLOR_MATERIAL);
      glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mat );
      for (int i=0; i<16; i++) mleg[i]=mat[i];
      mleg[0]=mleg[5]=mleg[10]=1.0;
      mleg[1]=mleg[2]=mleg[4]=mleg[6]=mleg[8]=mleg[9]=0.0;
      mleg[12]=mleg[13]=0;
      glLoadMatrixd(mleg);
      glPushMatrix();{
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective_( .1, (double)lw/lh, 5.0, 8000.0 );
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();{
          glDisable( GL_DEPTH_TEST );
          glScaled(.025,.025,.025);
          mol->tubes=0;
          mol->dratom=0;
          mol->intern=1;
          mol->adp=(drawADP)?1:0;
          glEnable(GL_CULL_FACE);
          mol->atoms(mol->legendAtoms,50,0.5);
          if (true){
            //printf("labScal=%f\n",labScal);
            //printf("ratio %f %f lw=%f %d\n",(double)ww/wh,lw/wh,lw,wh);
            double labScal_=0.35;
            if (mol->legendAtoms.size()+4!=extraTextures.size()) updateLabelTextures();
            glDisable(GL_CULL_FACE);
            glDisable(GL_DEPTH_TEST);
            glEnable(GL_BLEND);
            glEnable(GL_ALPHA_TEST);
            //glBindTexture(GL_TEXTURE_2D, t);
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            glEnable(GL_TEXTURE_2D);
            for (int li=0; li<mol->legendAtoms.size();li++){
              if (mol->legendAtoms.at(li).hidden) continue;
              if ((mol->legendAtoms.at(li).an==-1)&&(mol->noQPeaksPlease)) continue;
              qglColor(labelColor);
              glPushMatrix();{
                GLdouble mmm[16];
                GLuint t=bindTexture(extraTextures.at(li+4),GL_TEXTURE_2D);
                //printf("t=%d %d %d\n",t,extraTextures.size(),mol->legendAtoms.size());
                double ratio=(double)extraTextures.at(li+4).width()/extraTextures.at(li+4).height();
                glTranslated(mol->legendAtoms.at(li).pos.x,mol->legendAtoms.at(li).pos.y-0.2,mol->legendAtoms.at(li).pos.z);
                glGetDoublev( GL_MODELVIEW_MATRIX, (double*)mmm);
                double ddd = mmm[0] * (mmm[5] * mmm[10] - mmm[9] * mmm[6])
                  - mmm[1] * (mmm[4] * mmm[10] - mmm[8] * mmm[6])
                  + mmm[2] * (mmm[4] *  mmm[9] - mmm[8] * mmm[5]);
                ddd=pow(ddd,1.0/3.0);
                ddd*=(mol->legendAtoms.at(li).an>=0)?1.0:0.75;
                mmm[0]= ddd * labScal_ * ratio;
                mmm[5]= ddd * labScal_;
                mmm[10]=ddd * labScal_;
                mmm[1]=mmm[2]=mmm[4]=mmm[6]=mmm[8]=mmm[9]=0.0;
                glLoadMatrixd(mmm);
                mol->billBoard();
                deleteTexture(t);
                glPopMatrix();}
            }
            glDisable(GL_TEXTURE_2D);
            glEnable(GL_BLEND);
            glDisable(GL_ALPHA_TEST);
            glEnable(GL_DEPTH_TEST);

          }
          glPopMatrix();}
        glEnable( GL_DEPTH_TEST );
        glPopMatrix();}
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective_( viewAngle, (double)ww/wh, 5.0, 8000.0 );
      glMatrixMode(GL_MODELVIEW);
      glViewport(0, 0, ww, wh);
      glLoadMatrixd(mat);
      glPopMatrix();}
    /*for (int i=0;i< mol->legendAtoms.size(); i++) {
      if (mol->legendAtoms.at(i).hidden) continue;
      qglColor(labelColor);
      renderText(//965
      ww*0.045,
      wh-5-i*wh/29,
    //      mol->legendAtoms.at(i).pos.z,
    mol->legendAtoms.at(i).Label,
    myFont);
    }*/
  }///*
  mol->mist=depthcueing;
  // */
  afok=imFokus;
  //printf("draw %d objs%d\n",__LINE__,objCnt);
}
