//
//  kjots
//
//  Copyright (C) 1997 Christoph Neerfeld
//  email:  Christoph.Neerfeld@home.ivm.de or chris@kde.org
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//


//
// 1999-11-07-Espen Sand:
// Cleaned up layout, AskFileName based on KDialogBase,
// new Option dialog, QMessageBox -> KMessageBox
//


#include <qpopupmenu.h>
#include <qkeycode.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qdir.h>
#include <qlineedit.h>
#include <qobjectlist.h>
#include <qtooltip.h>
#include <qscrollbar.h>
#include <qcollection.h>
#include <qclipboard.h>

#include <kaccel.h>
#include <kaction.h>
#include <kstdaction.h>
#include <kapp.h>
#include <kfiledialog.h>

#include <kiconloader.h>
#include <kkeydialog.h>
#include <kmenubar.h>
#include <kmessagebox.h>
#include <kstddirs.h>
#include <ktoolbar.h>

extern "C" {
#include <unistd.h>
};

#include "KJotsMain.h"
#include "SubjList.h"
#include "ReadListConf.h"
#include "cpopmenu.h"
#include "optiondialog.h"

#include <klocale.h>
#include <kconfig.h>

#define KJOTSVERSION "0.4"

const unsigned int HOT_LIST_SIZE = 8;
const unsigned int BUTTON_WIDTH = 56;

extern QString exec_http;
extern QString exec_ftp;

#include <qvbox.h>

//----------------------------------------------------------------------
// ASKFILENAME
//----------------------------------------------------------------------
AskFileName::AskFileName(QWidget* parent, const char* name)
  : KDialogBase( parent, name, TRUE, i18n("New Book"), Ok|Cancel, Ok )
{
  QFrame *page = makeMainWidget();
  QVBoxLayout *vlay = new QVBoxLayout( page, 0, spacingHint() );

  QLabel *label = new QLabel( i18n("Book name:"), page );
  vlay->addWidget(label);

  i_name = new QLineEdit( page );
  i_name->setMinimumWidth( fontMetrics().maxWidth()*20 );
  i_name->setFocus();
  vlay->addWidget(i_name );
  connect(i_name, SIGNAL(textChanged(const QString &)),
	  this, SLOT(textChanged(const QString &)));

  vlay->addStretch( 10 );

  enableButtonOK( false );
}

void AskFileName::textChanged(const QString &s)
{
  enableButtonOK( s.length() > 0 );
}


//----------------------------------------------------------------------
// MYMULTIEDIT
//----------------------------------------------------------------------
MyMultiEdit::MyMultiEdit (QWidget* parent, const char* name)
  : KEdit(parent, name)
{
  web_menu = new CPopupMenu;
  web_menu->insertItem(i18n("Open URL"), this, SLOT(openUrl()) );
}

void MyMultiEdit::keyPressEvent( QKeyEvent *e )
{
  if( e->key() == Key_Tab )
    {
      int line, col;
      cursorPosition(&line, &col);
      KEdit::insertAt("\t", line, col);
      return;
    }
  KEdit::keyPressEvent(e);
  return;
}

void MyMultiEdit::mousePressEvent( QMouseEvent *e )
{
  if( e->button() == RightButton )
    {
      if( hasMarkedText() )
	{
	  QString marked = markedText();
	  if( marked.left(7) == "http://" || marked.left(6) == "ftp://" )
	    {
	      web_menu->popup(QCursor::pos());
	      web_menu->grabMouse();
	    }
      return;
	}
    }
  KEdit::mousePressEvent(e);
}

void MyMultiEdit::openUrl()
{
  QString command;
  int pos;
  if( hasMarkedText() )
    {
      QString marked = markedText();
      if( marked.left(7) == "http://" )
	{
	  command = exec_http;
	
	  if( (pos = exec_http.find("%u")) == -1 )
	    {
	      command += " " + marked + " &";
	    }
	  else
	    {
	      command.remove(pos, 2);
	      command = command.insert(pos, marked);
	      command += " &";
	    }
	  system((const char *) command);
	  //debug("exec: %s", (const char *) command );
	}
      else if( marked.left(6) == "ftp://" )
	{
	  command = exec_ftp;
	
	  if( (pos = exec_ftp.find("%u")) == -1 )
	    {
	      command += " " + marked + " &";
	    }
	  else
	    {
	      command.remove(pos, 2);
	      command = command.insert(pos, marked);
	      command += " &";
	    }
	  system((const char *) command);
	  //debug("exec: %s", (const char *) command );
	}
    }
}

//----------------------------------------------------------------------
// MYBUTTONGROUP
//----------------------------------------------------------------------

MyButtonGroup::MyButtonGroup (QWidget* parent, const char* name)
  : QButtonGroup(parent, name)
{
  initMetaObject();
}

void MyButtonGroup::resizeEvent( QResizeEvent * )
{
  int x = width()-2;
  QObjectList  *list = queryList( "QPushButton" );
  QObjectListIt it( *list );
  while ( it.current() ) {
    x -= (BUTTON_WIDTH+4);
    ((QPushButton *) it.current())->move(x, 4);
    ++it;
  }
  delete list;
}

//----------------------------------------------------------------------
// KJOTSMAIN
//----------------------------------------------------------------------

KJotsMain::KJotsMain(const char* name)
  : KTMainWindow( name )
{
  mOptionDialog = 0;
  folderOpen    = FALSE;
  current       = 0;

  //
  // Main widget
  //
  f_main = new QFrame( this, "Frame_0" );
  f_main->setFrameStyle( QFrame::NoFrame );
  setView(f_main, FALSE);

  //
  // Text area
  //
  f_text = new QFrame( f_main, "Frame_1" );
  f_text->setFrameStyle( QFrame::NoFrame );

  //
  // Status bar area
  //
  f_labels = new QFrame( f_main, "Frame_2" );
  f_labels->setFrameStyle( QFrame::NoFrame );

  //
  // Data widgets.
  //
  s_bar = new QScrollBar( f_main, "ScrollBar_1" );
  s_bar->setOrientation( QScrollBar::Horizontal );
  s_bar->setRange(0,0);
  s_bar->setValue(0);
  s_bar->setSteps(1,1);
  connect( s_bar, SIGNAL(valueChanged(int)), this, SLOT(barMoved(int)) );

  me_text = new MyMultiEdit( f_text, "me_text" );
  me_text->setMinimumWidth( fontMetrics().maxWidth()*40 );
  me_text->setFocusPolicy(QWidget::StrongFocus);
  me_text->setEnabled(FALSE);

  l_folder = new QLabel( f_labels, "Label_4" );
  l_folder->setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
  QFont font_label(l_folder->fontInfo().family());
  font_label.setBold(TRUE);
  l_folder->setFont(font_label);

  le_subject = new QLineEdit( f_labels, "le_subject" );
  le_subject->setFocusPolicy(QWidget::ClickFocus);
  le_subject->setEnabled(FALSE);

  l_folder->setMinimumWidth( fontMetrics().maxWidth()*8 );
  l_folder->setFixedHeight( le_subject->sizeHint().height() );

  bg_top = new MyButtonGroup( f_main, "ButtonGroup_2" );
  bg_top->setMinimumHeight( 32 ); // Bad!
  bg_top->setFrameStyle( QFrame::Box | QFrame::Sunken );
  bg_top->setExclusive(TRUE);

  //
  // Put data widgets into layouts
  //
  QVBoxLayout *l1 = new QVBoxLayout(f_text, 0, 0);
  l1->addWidget(me_text);

  QHBoxLayout *l2 = new QHBoxLayout(f_labels);
  l2->addWidget(l_folder);
  l2->addWidget(le_subject, 1 );

  QVBoxLayout *tl = new QVBoxLayout(f_main, 4);
  tl->addWidget(f_text, 1);
  tl->addWidget(s_bar);
  tl->addWidget(bg_top);
  tl->addWidget(f_labels);



  entrylist.setAutoDelete(TRUE);
  entrylist.append(new TextEntry);
  button_list.setAutoDelete(TRUE);

  subj_list = new SubjList( topLevelWidget(), 0, false );
  connect( this, SIGNAL(folderChanged(QList<TextEntry> *)),
	   subj_list, SLOT(rebuildList( QList<TextEntry> *)) );
  connect( this, SIGNAL(entryMoved(int)),
	   subj_list, SLOT( select(int)) );
  connect( subj_list, SIGNAL(entryMoved(int)),
	   this, SLOT( barMoved(int)) );
  connect( le_subject, SIGNAL(textChanged(const QString &)),
	   subj_list, SLOT(entryChanged(const QString &)) );



  KConfig *config = kapp->config();
  config->setGroup("kjots");

  // read hotlist
  config->readListEntry( "Hotlist", hotlist );
  while( hotlist.count() > HOT_LIST_SIZE )
    hotlist.removeLast();
  // read list of folders
  config->readListEntry( "Folders", folder_list );

  QString temp;
  folders = new QPopupMenu;
  int i = 0;
  QPushButton *temp_button;
  for( temp=folder_list.first(); !temp.isEmpty(); temp=folder_list.next(), i++)
  {
    folders->insertItem(temp, i);
    if( hotlist.contains(temp) )
    {
      temp_button = new QPushButton(temp, bg_top);
      temp_button->setFocusPolicy(QWidget::ClickFocus);
      temp_button->setToggleButton(TRUE);
      temp_button->setFixedSize(BUTTON_WIDTH,24);
      bg_top->insert(temp_button, i);
      button_list.append(temp_button);
    }
  }

  unique_id = i+1;
  connect( folders, SIGNAL(activated(int)), this, SLOT(openFolder(int)) );
  connect( bg_top, SIGNAL(clicked(int)), this, SLOT(openFolder(int)) );

  updateConfiguration();

  // creat keyboard shortcuts
  // CTRL+Key_J := previous page
  // CTRL+Key_K := next page
  // CTRL+Key_L := show subject list
  // CTRL+Key_A := add new page
  // CTRL+Key_M := move focus

  keys = new KAccel( this );
  keys->insertStdItem( KStdAccel::New, i18n("New Book") );

  keys->connectItem( KStdAccel::New, this, SLOT(createFolder()) );
  keys->connectItem( KStdAccel::Save , this, SLOT(saveFolder()) );
  keys->connectItem( KStdAccel::Quit, qApp, SLOT(quit()) );
  keys->connectItem( KStdAccel::Cut , me_text, SLOT(cut()) );
  keys->connectItem( KStdAccel::Copy , me_text, SLOT(copyText()) );
  keys->connectItem( KStdAccel::Paste , me_text, SLOT(paste()) );

  keys->insertItem(i18n("PreviousPage"),    "PreviousPage",    CTRL+Key_J);
  keys->insertItem(i18n("NextPage"),        "NextPage",        CTRL+Key_K);
  keys->insertItem(i18n("ShowSubjectList"), "ShowSubjectList", CTRL+Key_L);
  keys->insertItem(i18n("AddNewPage"),      "AddNewPage",      CTRL+Key_A);
  keys->insertItem(i18n("DelPage"),          "DelPage",        CTRL+Key_D);
  keys->insertItem(i18n("MoveFocus"),       "MoveFocus",       CTRL+Key_M);
  keys->insertItem(i18n("CopySelection"),   "CopySelection",   CTRL+Key_Y);
  keys->connectItem( "PreviousPage", this, SLOT(prevEntry()) );
  keys->connectItem( "NextPage", this, SLOT(nextEntry()) );
  keys->connectItem( "ShowSubjectList", this, SLOT(toggleSubjList()) );
  keys->connectItem( "AddNewPage", this, SLOT(newEntry()) );
  keys->connectItem( "MoveFocus", this, SLOT(moveFocus()) );
  keys->connectItem( "CopySelection", this, SLOT(copySelection()) );
  keys->readSettings();

  
  // create menu
  int id;
  QPopupMenu *file = new QPopupMenu;
  id = file->insertItem(i18n("&New Book"), this, SLOT(createFolder()));
  keys->changeMenuAccel(file, id, KStdAccel::New);

  file->insertSeparator();
  id_f_save_book = file->insertItem(i18n("Save current book"),
				    this, SLOT(saveFolder()) );
  keys->changeMenuAccel(file, id_f_save_book, KStdAccel::Save);
  id_f_save_book_ascii = file->insertItem(i18n("Save book to ascii file"),
					  this, SLOT(writeBook()) );
  id_f_save_page_ascii = file->insertItem(i18n("Save page to ascii file"),
					  this, SLOT(writePage()) );
  file->insertSeparator();
  id_f_del_book = file->insertItem(i18n("Delete current book"),
				   this, SLOT(deleteFolder()) );
  file->insertSeparator();
  id = file->insertItem(i18n("&Quit"),
			qApp, SLOT(quit()));
  keys->changeMenuAccel(file, id, KStdAccel::Quit);

  QPopupMenu *edit_menu = new QPopupMenu;

  id_e_cut = edit_menu->insertItem(i18n("C&ut"),
				   me_text, SLOT(cut()));
  keys->changeMenuAccel(edit_menu, id_e_cut, KStdAccel::Cut);
  id_e_copy = edit_menu->insertItem(i18n("&Copy") ,
				    me_text, SLOT(copyText()) );
  keys->changeMenuAccel(edit_menu, id_e_copy, KStdAccel::Copy);
  id_e_paste = edit_menu->insertItem(i18n("&Paste"),
				     me_text, SLOT(paste()));
  keys->changeMenuAccel(edit_menu, id_e_paste, KStdAccel::Paste);
  edit_menu->insertSeparator();
  
  // added actionized items (pfeiffer)
  KAction *action = KStdAction::find( this, SLOT( slotSearch() ), me_text );
  action->plug( edit_menu );
  action = KStdAction::findNext( this, SLOT( slotRepeatSearch() ), me_text );
  action->plug( edit_menu );
  action = KStdAction::replace( this, SLOT( slotReplace() ), me_text );
  action->plug( edit_menu );
  edit_menu->insertSeparator();
  
  id_e_new = edit_menu->insertItem(i18n("&New Page"),
				   this, SLOT(newEntry()) );
  keys->changeMenuAccel(edit_menu, id_e_new, "AddNewPage");
  id_e_del = edit_menu->insertItem(i18n("&Delete Page"),
				   this, SLOT(deleteEntry()) );
  keys->changeMenuAccel(edit_menu, id_e_del, "DelPage");

  QPopupMenu *options = new QPopupMenu;
  options->insertItem(i18n("Configure &Key Bindings"),
		      this, SLOT(configureKeys()) );
  options->insertItem(i18n("&Configure %1...").arg(kapp->caption()),
		      this, SLOT(configure()) );

  QPopupMenu *hotlist = new QPopupMenu;
  id_fav_add = hotlist->insertItem(i18n("Add current book to hotlist"),
				   this, SLOT(addToHotlist()) );
  id_fav_del = hotlist->insertItem(i18n("Remove current book from hotlist"),
				   this, SLOT(removeFromHotlist()) );

  menuBar()->insertItem( i18n("&File"), file );
  menuBar()->insertItem( i18n("&Edit"), edit_menu );
  menuBar()->insertItem( i18n("&Books"), folders );
  menuBar()->insertItem( i18n("Hot&list"), hotlist );
  menuBar()->insertItem( i18n("&Options"), options );
  menuBar()->insertSeparator();
  QString about = "KJots " KJOTSVERSION "\n\r(c) ";
  about += (QString) i18n("by") +
    " Christoph Neerfeld\n\rChristoph.Neerfeld@home.ivm.de";
  menuBar()->insertItem( i18n("&Help"), helpMenu(about ) );

  //
  // Make toolbar
  //
  QPixmap temp_pix;
  temp_pix = BarIcon("filenew");
  toolBar(0)->insertButton(temp_pix, 0, SIGNAL(clicked()), this,
			   SLOT(newEntry()), TRUE, i18n("New"));
  temp_pix = BarIcon("filedel");
  toolBar(0)->insertButton(temp_pix, 1, SIGNAL(clicked()), this,
			   SLOT(deleteEntry()), TRUE, i18n("Delete"));
  temp_pix = BarIcon("back");
  toolBar(0)->insertButton(temp_pix, 2, SIGNAL(clicked()), this,
			   SLOT(prevEntry()), TRUE, i18n("Previous"));
  temp_pix = BarIcon("forward");
  toolBar(0)->insertButton(temp_pix, 3, SIGNAL(clicked()), this,
			   SLOT(nextEntry()), TRUE, i18n("Next"));
  toolBar(0)->insertSeparator();
  temp_pix = BarIcon("openbook");
  toolBar(0)->insertButton(temp_pix, 4, SIGNAL(clicked()), this,
			   SLOT(toggleSubjList()), TRUE, i18n("Subject List"));
  toolBar(0)->insertSeparator();
  temp_pix = BarIcon("exit");

  config->setGroup("kjots");
  toolBar(0)->setBarPos(
    (KToolBar::BarPosition)config->readNumEntry("ToolBarPos"));
  enableToolBar(KToolBar::Show);


  int nr = folder_list.find( config->readEntry("LastOpenFolder") );
  if( nr >= 0 )
  {
    openFolder(nr);
  }

  //
  // Set minimum size of main widget
  //
  f_main->setMinimumSize( f_main->sizeHint() );

  //
  // Set startup size.
  //
  int w = config->readNumEntry("Width");
  int h = config->readNumEntry("Height");
  w = QMAX( w, sizeHint().width() );
  h = QMAX( h, sizeHint().height() );
  resize(w, h);

  updateMenu();
}



KJotsMain::~KJotsMain()
{
  delete mOptionDialog;
  saveProperties();
}


void KJotsMain::saveProperties( void )
{
  KConfig &config = *kapp->config();
  config.setGroup("kjots");
  button_list.clear();
  if( folderOpen )
  {
    QFileInfo fi(current_folder_name);
    config.writeEntry("LastOpenFolder", fi.fileName());
  }
  saveFolder();
  config.writeEntry("Width", width());
  config.writeEntry("Height", height());
  config.writeEntry("ToolBarPos", (int)toolBar(0)->barPos() );
  config.sync();
}


int KJotsMain::readFile( QString name )
{
  int pos;
  QString buf, subj;
  TextEntry *entry;

  entrylist.clear();
  QFile folder(name);
  if( !folder.open(IO_ReadWrite) )
    return -1;
  QTextStream st( (QIODevice *) &folder);
  buf = st.readLine();
  if( buf.left(9) != "\\NewEntry" )
    return -1;
  entry = new TextEntry;
  entrylist.append( entry );
  subj = buf.mid(10, buf.length() );
  entry->subject = subj.isNull() ? (QString) "" : (QString) subj;
  while( !st.eof() )
    {
      buf = st.readLine();
      if( buf.left(9) == "\\NewEntry" )
	{
	  entry = new TextEntry;
	  entrylist.append(entry);
	  subj = buf.mid(10, buf.length() );
	  entry->subject = subj.isNull() ? (QString) "" : (QString) subj;
	  buf = st.readLine();
	}
      pos = 0;
      while( (pos = buf.find( '\\', pos )) != -1 )
	if( buf[++pos] == '\\' )
	  buf.remove( pos, 1 );
      entry->text.append( buf );
      entry->text.append("\n");
    }
  folder.close();
  while( entry->text.right(1) == "\n" )
    entry->text.truncate(entry->text.length() - 1);
  entry->text.append("\n");

  updateMenu();
  return 0;
}

int KJotsMain::writeFile( QString name ) {
  int pos;
  TextEntry *entry;
  QString buf;
  QFile folder(name);
  if( !folder.open(IO_WriteOnly | IO_Truncate) )
    return -1;
  QTextStream st( (QIODevice *) &folder);
  for( entry = entrylist.first(); entry != NULL; entry = entrylist.next() )
    {
      st << "\\NewEntry ";
      st << entry->subject;
      st << "\n";
      buf = entry->text;

      pos = 0;
      while( (pos = buf.find( '\\', pos )) != -1 )
	{
	  buf.insert( ++pos, '\\' );
	  pos++;
	}
      st << buf;
      if( buf.right(1) != "\n" )
	st << '\n';
    }
  folder.close();
  return 0;
}

void KJotsMain::openFolder(int id) {
  QPushButton *but;

  for( but = button_list.first(); but != NULL; but = button_list.next() )
    but->setOn(FALSE);
  but = (QPushButton *) bg_top->find(id);
  if( but )
    but->setOn(TRUE);

  QDir dir = QDir( locateLocal("appdata", "") );
  QString file_name = dir.absPath();
  file_name += '/';
  file_name += folder_list.at( folders->indexOf(id) );
  if( current_folder_name == file_name )
    return;
  if( folderOpen )
    saveFolder();
  current_folder_name = file_name;

  if( readFile(current_folder_name) < 0)
    {
      folderOpen = FALSE;
      debug("Kjots: Unable to open folder");
      return;
    }

  current = 0;
  me_text->deselect();
  me_text->setText(entrylist.first()->text);
  emit folderChanged(&entrylist);
  emit entryMoved(current);
  le_subject->setText(entrylist.first()->subject);
  folderOpen = TRUE;
  l_folder->setText( folder_list.at(folders->indexOf(id)) );
  me_text->setEnabled(TRUE);
  le_subject->setEnabled(TRUE);
  me_text->setFocus();
  s_bar->setRange(0,entrylist.count()-1);
  s_bar->setValue(0);

  updateMenu();
}


void KJotsMain::createFolder()
{
  AskFileName *ask = new AskFileName(this);
  if( ask->exec() == QDialog::Rejected )
  {
    delete ask;
    return;
  }

  QString name = ask->getName();
  delete ask;
  if( folder_list.contains(name) )
  {
    QString msg = i18n("A book with this name already exists.");
    KMessageBox::sorry( topLevelWidget(), msg );
    return;
  }

  saveFolder();
  entrylist.clear();
  folderOpen = TRUE;
  me_text->setEnabled(TRUE);
  le_subject->setEnabled(TRUE);
  me_text->setFocus();
  me_text->clear();
  me_text->deselect();
  TextEntry *new_entry = new TextEntry;
  entrylist.append(new_entry);
  new_entry->subject = "";
  current = 0;
  s_bar->setRange(0,0);
  s_bar->setValue(0);
  emit folderChanged(&entrylist);
  emit entryMoved(current);
  le_subject->setText(entrylist.first()->subject);

  folder_list.append(name);

  // TODO: this does not work with qt 2.0. Why?
//     if( folders->text(folders->idAt(0)) == 0 )
//      folders->removeItemAt(0);

  folders->insertItem(name, unique_id++);
  QDir dir = QDir( locateLocal("appdata", "") );
  current_folder_name = dir.absPath();
  current_folder_name += '/';
  current_folder_name += name;
  KConfig *config = KApplication::kApplication()->config();
  config->setGroup("kjots");
  config->writeEntry( "Folders", folder_list );
  config->sync();
  l_folder->setText(name);
  QPushButton *but;
  for( but = button_list.first(); but != 0; but = button_list.next() )
    but->setOn(FALSE);

  updateMenu();
}

void KJotsMain::deleteFolder()
{
  if( !folderOpen )
    return;

  QString msg = i18n("Are you sure you want to delete the current book ?");
  int result = KMessageBox::warningYesNo( topLevelWidget(), msg );
  if( result != KMessageBox::Yes )
  {
    return;
  }

  QFileInfo fi(current_folder_name);
  QDir dir = fi.dir(TRUE);
  QString name = fi.fileName();
  int index = folder_list.find(name);
  if( index < 0 )
    return;
  dir.remove(current_folder_name);
  folder_list.remove(index);
  int id = folders->idAt(index);
  folders->removeItemAt(index);
  if( hotlist.contains(name) )
    {
      hotlist.remove(name);
      QButton *but = bg_top->find(id);
      bg_top->remove(but);
      button_list.remove( (QPushButton *) but );
      resize(size());
    }
  KConfig *config = KApplication::kApplication()->config();
  config->setGroup("kjots");
  config->writeEntry( "Folders", folder_list );
  config->writeEntry( "Hotlist", hotlist );
  config->sync();
  entrylist.clear();
  current_folder_name = "";
  folderOpen = FALSE;
  me_text->setEnabled(FALSE);
  me_text->clear();
  me_text->deselect();
  le_subject->setEnabled(FALSE);
  le_subject->clear();
  emit folderChanged(&entrylist);
  s_bar->setRange(0,0);
  s_bar->setValue(0);
  l_folder->clear();
  subj_list->repaint(TRUE);

  updateMenu();
}

void KJotsMain::saveFolder()
{
  if( !folderOpen )
    return;
  entrylist.at(current)->text = me_text->text();
  entrylist.at(current)->subject = le_subject->text();
  writeFile(current_folder_name);
}

void KJotsMain::nextEntry()
{
  if( !folderOpen )
    return;
  if( current+1 >= (int) entrylist.count() )
    return;
  entrylist.at(current)->text = me_text->text();
  entrylist.at(current)->subject = le_subject->text();
  me_text->setText( entrylist.at(++current)->text );
  me_text->deselect();
  me_text->repaint();
  emit entryMoved(current);
  le_subject->setText( entrylist.at(current)->subject );
  s_bar->setValue(current);

  updateMenu();
}

void KJotsMain::prevEntry()
{
  if( !folderOpen )
    return;
  if( current-1 < 0 )
    return;
  entrylist.at(current)->text = me_text->text();
  entrylist.at(current)->subject = le_subject->text();
  me_text->setText( entrylist.at(--current)->text );
  me_text->deselect();
  me_text->repaint();
  emit entryMoved(current);
  le_subject->setText( entrylist.at(current)->subject );
  s_bar->setValue(current);

  updateMenu();
}

void KJotsMain::newEntry()
{
  if( !folderOpen )
    return;
  entrylist.at(current)->text = me_text->text();
  entrylist.at(current)->subject = le_subject->text();
  me_text->clear();
  le_subject->clear();
  TextEntry *new_entry = new TextEntry;
  entrylist.append(new_entry);
  new_entry->subject = "";
  current = entrylist.count()-1;
  s_bar->setRange(0,current);
  s_bar->setValue(current);
  emit folderChanged(&entrylist);
  emit entryMoved(current);

  updateMenu();
}

void KJotsMain::deleteEntry()
{
  if( !folderOpen )
    return;
  if( entrylist.count() == 0 )
    return;
  else if( entrylist.count() == 1 )
    {
      entrylist.at(0)->text = "";
      entrylist.at(0)->subject = "";
      s_bar->setValue(0);
      me_text->clear();
      le_subject->clear();
      return;
    }
  entrylist.remove(current);
  if( current >= (int) entrylist.count() - 1 )
    {
      if( current )
      current--;
      s_bar->setValue(current);
      s_bar->setRange(0, entrylist.count()-1 );
    }
  me_text->setText( entrylist.at(current)->text );
  emit entryMoved(current);
  le_subject->setText( entrylist.at(current)->subject );
  s_bar->setRange(0, entrylist.count()-1 );
  emit folderChanged(&entrylist);

  updateMenu();
}

void KJotsMain::barMoved( int new_value )
{
  if( !folderOpen )
    return;
  if( current == new_value )
    return;
  entrylist.at(current)->text = me_text->text();
  entrylist.at(current)->subject = le_subject->text();
  current = new_value;
  me_text->setText( entrylist.at(current)->text );
  me_text->deselect();
  me_text->repaint();
  emit entryMoved(current);
  le_subject->setText( entrylist.at(current)->subject );
  s_bar->setValue(new_value);

  updateMenu();
}

void KJotsMain::addToHotlist()
{
  if( hotlist.count() == HOT_LIST_SIZE )
    return;
  QFileInfo fi(current_folder_name);
  QString name = fi.fileName();
  if( hotlist.contains(name) )
    return;
  hotlist.append(name);
  int index = folder_list.find(name);
  if( index < 0 )
    return;
  int id = folders->idAt(index);
  QPushButton *but = new QPushButton(name, bg_top);
  button_list.append(but);
  bg_top->insert(but, id);
  KConfig *config = KApplication::kApplication()->config();
  config->setGroup("kjots");
  config->writeEntry( "Hotlist", hotlist );
  config->sync();
  but->setFocusPolicy(QWidget::ClickFocus);
  but->setToggleButton(TRUE);
  but->setFixedSize(BUTTON_WIDTH, 24);
  but->show();
  but->setOn(TRUE);
  bg_top->forceResize();
}

void KJotsMain::removeFromHotlist()
{
  QFileInfo fi(current_folder_name);
  QString name = fi.fileName();
  if( !hotlist.contains(name) )
    return;
  hotlist.remove(name);
  int index = folder_list.find(name);
  if( index < 0 )
    return;
  int id = folders->idAt(index);
  QButton *but = bg_top->find(id);
  bg_top->remove(but);
  button_list.remove( (QPushButton *) but );
  KConfig *config = KApplication::kApplication()->config();
  config->setGroup("kjots");
  config->writeEntry( "Hotlist", hotlist );
  config->sync();
  bg_top->forceResize();
}

void KJotsMain::toggleSubjList()
{
  if( subj_list->isVisible() )
  {
    subj_list->hide();
  }
  else
  {
    subj_list->setInitialSize( QSize(width()/2,height()) );
   //subj_list->resize( QSize(width() / 2, height()) );
    subj_list->show();
  }
}

void KJotsMain::configure()
{
  if( mOptionDialog == 0 )
  {
    mOptionDialog = new ConfigureDialog( topLevelWidget(), 0, false );
    if( mOptionDialog == 0 ) { return; }
    connect( mOptionDialog, SIGNAL(hidden()),this,SLOT(configureHide()));
    connect( mOptionDialog, SIGNAL(valueChanged()),
	     this, SLOT(updateConfiguration()) );
  }

  mOptionDialog->show();
}

void KJotsMain::configureHide()
{
  QTimer::singleShot( 0, this, SLOT(configureDestroy()) );
}

void KJotsMain::configureDestroy()
{
  if( mOptionDialog != 0 && mOptionDialog->isVisible() == false )
  {
    delete mOptionDialog; mOptionDialog = 0;
  }
}

void KJotsMain::slotSearch()
{
    me_text->search();
}

void KJotsMain::slotRepeatSearch()
{
    me_text->repeatSearch();
}

void KJotsMain::slotReplace()
{
    me_text->replace();
}

void KJotsMain::updateConfiguration()
{
  KConfig &config = *kapp->config();

  config.setGroup("kjots");
  exec_http = config.readEntry("execHttp");
  exec_ftp  = config.readEntry("execFtp");
  QFont font( config.readEntry("EFontFamily"),
	      config.readNumEntry("EFontSize"),
	      config.readNumEntry("EFontWeight"),
	      config.readNumEntry("EFontItalic"),
	      (QFont::CharSet) config.readNumEntry("EFontCharset") );
  me_text->setFont(font);
}

void KJotsMain::writeBook()
{
  saveFolder();
  QString name;
  while( name.isNull() )
  {
    KURL url = KFileDialog::getSaveURL();

    if ( url.isEmpty() )
      return;

    if ( !url.isLocalFile() )
    {
      KMessageBox::sorry( 0L, i18n( "Only local files supported yet." ) );
      return;
    }

    name = url.path();

    QFileInfo f_info(name);
    if( f_info.exists() )
    {
      QString msg = i18n(""
        "File already exists.\n"
	"Do you want to overwrite it ? ");
      int result = KMessageBox::warningYesNo( topLevelWidget(), msg );
      if( result != KMessageBox::Yes )
      {
	name = "";
      }
    }
  }
  QFile ascii_file(name);
  if( !ascii_file.open(IO_WriteOnly | IO_Truncate) )
    return;
  QTextStream st( (QIODevice *) &ascii_file);
  TextEntry *entry;
  for( entry = entrylist.first(); entry != NULL; entry = entrylist.next() )
    {
      writeEntry( st, entry );
    }
  ascii_file.close();
}

void KJotsMain::writePage()
{
  saveFolder();
  QString name;
  while( name.isNull() )
  {
    KURL url = KFileDialog::getSaveURL();

    if( url.isEmpty() )
      return;

    if( !url.isLocalFile() )
    {
      KMessageBox::sorry( 0L, i18n( "Only local files supported yet." ) );
      return;
    }

    name = url.path();

    QFileInfo f_info(name);
    if( f_info.exists() )
    {
      QString msg = i18n(""
        "File already exists.\n"
	"Do you want to overwrite it ? ");
      int result = KMessageBox::warningYesNo( topLevelWidget(), msg );
      if( result != KMessageBox::Yes )
      {
	name = "";
      }
    }
  }
  QFile ascii_file(name);
  if( !ascii_file.open(IO_WriteOnly | IO_Truncate) )
    return;
  QTextStream st( (QIODevice *) &ascii_file);
  writeEntry( st, entrylist.at(current) );
  ascii_file.close();
}

void KJotsMain::writeEntry( QTextStream &st, TextEntry *entry )
{
  QString line, buf;
  line.fill('#', entry->subject.length()+2 );
  st << line << '\n';
  st << "# ";
  st << entry->subject << '\n';
  st << line << '\n';
  buf = entry->text;
  st << buf;
  if( buf.right(1) != "\n" )
    st << '\n';
  st << '\n';
}

void KJotsMain::moveFocus()
{
  if( me_text->hasFocus() )
    le_subject->setFocus();
  else
    me_text->setFocus();
}

void KJotsMain::configureKeys()
{
  if( KKeyDialog::configureKeys( keys, true, topLevelWidget() ) )
    keys->writeSettings();
}

void KJotsMain::copySelection()
{
  me_text->copyText();
  le_subject->setText(QApplication::clipboard()->text());
}


void KJotsMain::updateMenu()
{
  bool activeBook = folderOpen;

  menuBar()->setItemEnabled(id_f_save_book, activeBook);
  menuBar()->setItemEnabled(id_f_save_book_ascii, activeBook);
  menuBar()->setItemEnabled(id_f_save_page_ascii, activeBook);
  menuBar()->setItemEnabled(id_f_del_book, activeBook);

  menuBar()->setItemEnabled(id_e_cut, activeBook);
  menuBar()->setItemEnabled(id_e_copy, activeBook);
  menuBar()->setItemEnabled(id_e_paste, activeBook);
  menuBar()->setItemEnabled(id_e_new, activeBook);
  menuBar()->setItemEnabled(id_e_del, activeBook);

  menuBar()->setItemEnabled(id_fav_add, activeBook);
  menuBar()->setItemEnabled(id_fav_del, activeBook);
}
