You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kbookreader/src/bookreader.cpp

512 lines
14 KiB

/***************************************************************************
* Copyright (C) 2005 by Alexander Nemish *
* atlanter@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <kaccel.h>
#include <kaction.h>
#include <kcharsets.h>
#include <kconfig.h>
#include <kconfigdialog.h>
#include <kdebug.h>
#include <tdeversion.h>
#include <kencodingfiledialog.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <kinputdialog.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kmessagebox.h>
#include <kprinter.h>
#include <kstatusbar.h>
#include <ksplashscreen.h>
#include <kstandarddirs.h>
#include <kstdaccel.h>
#include <kstdaction.h>
#include <kurl.h>
#include <kurldrag.h>
#include <kurlrequesterdlg.h>
#include <kio/netaccess.h>
#include <tqdragobject.h>
#include <tqpainter.h>
#include <tqpaintdevicemetrics.h>
#include <tqpixmap.h>
#include <tqtextcodec.h>
#include <tqsignalmapper.h>
#include <assert.h>
#include "bookreader.h"
#include "settings.h"
#include "settingsdlg.h"
#include "bookmarksdlg.h"
namespace {
TQStringList listEncodings()
{
const TQStringList encodings(KGlobal::charsets()->availableEncodingNames());
TQStringList availEncodings;
for (unsigned int i=0; i < encodings.count(); ++i)
{
bool found = false;
KGlobal::charsets()->codecForName(encodings[i], found);
if (found)
availEncodings << encodings[i];
}
return availEncodings;
}
}
BookReader::BookReader()
: KMainWindow(0, "BookReader"),
m_view(new BookWidget(this)),
m_fullScreenAction(0),
m_splash(0),
m_printer(0)
{
TQPixmap splash(KGlobal::dirs()->findResource("appdata",
"themes/default/splash.png"));
m_splash = new KSplashScreen(splash);
m_splash->show();
// accept dnd
setAcceptDrops(true);
// tell the KMainWindow that this is indeed the main widget
setCentralWidget(m_view);
// then, setup our actions
setupActions();
// and a status bar
statusBar()->show();
// Apply the create the main window and ask the mainwindow to
// automatically save settings if changed: window size, toolbar
// position, icon size, etc. Also to add actions for the statusbar
// toolbar, and keybindings if necessary.
KStdAction::keyBindings(guiFactory(), TQT_SLOT(configureShortcuts()), actionCollection());
createStandardStatusBarAction();
setStandardToolBarMenuEnabled( true );
KStdAction::configureToolbars(TQT_TQOBJECT(this), TQT_SLOT(configureToolbars() ), actionCollection());
createGUI(TQString(), false);
initialGeometrySet();
setAutoSaveSettings();
// allow the view to change the statusbar and caption
connect(m_view, TQT_SIGNAL(signalChangeStatusbar(const TQString&)),
TQT_TQOBJECT(this), TQT_SLOT(changeStatusbar(const TQString&)));
connect(m_view, TQT_SIGNAL(signalChangeCaption(const TQString&)),
TQT_TQOBJECT(this), TQT_SLOT(changeCaption(const TQString&)));
readSettings();
m_splash->finish(m_view);
}
BookReader::~BookReader()
{
writeSettings();
delete m_splash;
}
void BookReader::load(const KURL& url)
{
TQString target;
// download the contents
if(!KIO::NetAccess::download(url, target, this))
{
KMessageBox::error(this, KIO::NetAccess::lastErrorString());
return;
}
recentFilesAction->addURL(url);
setCaption(url.fileName());
m_view->openURL(url);
updateBookmarks();
KIO::NetAccess::removeTempFile(target);
}
void BookReader::setupActions()
{
// KStdAction::openNew(TQT_TQOBJECT(this), TQT_SLOT(fileNew()), actionCollection());
KStdAction::open(TQT_TQOBJECT(this), TQT_SLOT(fileOpen()), actionCollection());
recentFilesAction = KStdAction::openRecent(TQT_TQOBJECT(this), TQT_SLOT(slotURLSelected(const KURL &)),
actionCollection());
KStdAction::save(TQT_TQOBJECT(this), TQT_SLOT(fileSave()), actionCollection());
KStdAction::saveAs(TQT_TQOBJECT(this), TQT_SLOT(fileSaveAs()), actionCollection());
KStdAction::print(TQT_TQOBJECT(this), TQT_SLOT(filePrint()), actionCollection());
KStdAction::quit(TQT_TQOBJECT(kapp), TQT_SLOT(quit()), actionCollection());
KStdAction::firstPage(TQT_TQOBJECT(this), TQT_SLOT(gotoFirstPage()), actionCollection());
KStdAction::prior(TQT_TQOBJECT(this), TQT_SLOT(prevPage()), actionCollection());
KStdAction::next(TQT_TQOBJECT(this), TQT_SLOT(nextPage()), actionCollection());
KStdAction::lastPage(TQT_TQOBJECT(this), TQT_SLOT(gotoLastPage()), actionCollection());
KStdAction::addBookmark(TQT_TQOBJECT(this), TQT_SLOT(addBookmark()), actionCollection());
KStdAction::editBookmarks(TQT_TQOBJECT(this), TQT_SLOT(editBookmarks()), actionCollection());
KStdAction::gotoPage(TQT_TQOBJECT(this), TQT_SLOT(gotoPage()), actionCollection());
m_fullScreenAction = KStdAction::fullScreen(TQT_TQOBJECT(this), TQT_SLOT(fullScreen()),
actionCollection(), this);
KStdAction::preferences(TQT_TQOBJECT(this), TQT_SLOT(optionsPreferences()), actionCollection());
KConfig *config = kapp->config();
recentFilesAction->loadEntries(config);
// this doesn't do anything useful. it's just here to illustrate
// how to insert a custom menu and menu item
/*
KAction *custom = new KAction( i18n( "Cus&tom Menuitem" ), 0,
TQT_TQOBJECT(this), TQT_SLOT( optionsPreferences() ),
actionCollection(), "custom_action" );*/
}
void BookReader::saveProperties(KConfig *config)
{
// the 'config' object points to the session managed
// config file. anything you write here will be available
// later when this app is restored
if (!m_view->currentURL().isEmpty())
{
config->writeEntry("lastURL", m_view->currentURL());
config->writeEntry("currentPage", m_view->currentPage());
}
}
void BookReader::readProperties(KConfig */*config*/)
{
// the 'config' object points to the session managed
// config file. this function is automatically called whenever
// the app is being restored. read in here whatever you wrote
// in 'saveProperties'
// TQString url = config->readPathEntry("lastURL");
// int currentPage = config->readEntry("currentPage").toInt();
/* Disable forawhile
if (!url.isEmpty())
{
m_view->openURL(KURL(url));
m_view->setCurrentPage(currentPage);
}
*/
}
void BookReader::dragEnterEvent(TQDragEnterEvent *event)
{
// accept uri drops only
event->accept(KURLDrag::canDecode(event));
}
void BookReader::dropEvent(TQDropEvent *event)
{
// this is a very simplistic implementation of a drop event. we
// will only accept a dropped URL. the TQt dnd code can do *much*
// much more, so please read the docs there
KURL::List urls;
// see if we can decode a URI.. if not, just ignore it
if (KURLDrag::decode(event, urls) && !urls.isEmpty())
{
// okay, we have a URI.. process it
const KURL & url = urls.first();
// load in the file
load(url);
}
}
void BookReader::fileOpen()
{
// this slot is called whenever the File->Open menu is selected,
// the Open shortcut is pressed (usually CTRL+O) or the Open toolbar
// button is clicked
/*
// this brings up the generic open dialog
KURL url = KURLRequesterDlg::getURL(TQString(), this, i18n("Open Location") );
*/
// standard filedialog
KEncodingFileDialog::Result res =
KEncodingFileDialog::getOpenURLAndEncoding(
listEncodings()[Settings::defaultEncoding()]);
KURL url = res.URLs.front();
m_view->setEncoding(res.encoding);
if (!url.isEmpty())
load(url);
}
void BookReader::fileSave()
{
// this slot is called whenever the File->Save menu is selected,
// the Save shortcut is pressed (usually CTRL+S) or the Save toolbar
// button is clicked
// save the current file
}
void BookReader::fileSaveAs()
{
// this slot is called whenever the File->Save As menu is selected,
KURL file_url = KFileDialog::getSaveURL();
if (!file_url.isEmpty() && file_url.isValid())
{
// save your info, here
}
}
void BookReader::filePrint()
{
// this slot is called whenever the File->Print menu is selected,
// the Print shortcut is pressed (usually CTRL+P) or the Print toolbar
// button is clicked
if (!m_printer) m_printer = new KPrinter;
if (m_printer->setup(this))
{
// setup the printer. with TQt, you always "print" to a
// TQPainter.. whether the output medium is a pixmap, a screen,
// or paper
TQPainter p;
p.begin(m_printer);
// we let our view do the actual printing
TQPaintDeviceMetrics metrics(m_printer);
//m_view->print( &p, metrics.height(), metrics.width() );
// and send the result to the printer
p.end();
}
}
void BookReader::optionsPreferences()
{
if (KConfigDialog::showDialog("settings"))
return ;
KConfigDialog *dialog = new KConfigDialog(this, "settings", Settings::self(),
KDialogBase::IconList);
SettingsWidget *general = new SettingsWidget(0, "General");
const TQStringList encodings(listEncodings());
TQString curEncoding(encodings[Settings::defaultEncoding()]);
if (curEncoding.isEmpty())
curEncoding = TQString::tqfromLatin1(KGlobal::locale()->encoding());
general->kcfg_DefaultEncoding->clear();
general->kcfg_DefaultEncoding->insertStringList(encodings);
for (unsigned int i=0; i < encodings.count(); ++i)
if (encodings[i] == curEncoding)
general->kcfg_DefaultEncoding->setCurrentItem(i);
dialog->addPage(general, i18n("General"), "settings");
connect(dialog, TQT_SIGNAL(settingsChanged()), TQT_TQOBJECT(this), TQT_SLOT(loadSettings()));
dialog->show();
}
void BookReader::changeStatusbar(const TQString& text)
{
// display the text on the statusbar
statusBar()->message(text);
}
void BookReader::changeCaption(const TQString& text)
{
// display the text on the caption
setCaption(text);
}
void BookReader::loadSettings()
{
m_view->setFont(Settings::font());
m_view->setParaOffset(Settings::paraOffset());
m_view->setEncoding(Settings::defaultEncoding());
}
void BookReader::slotURLSelected(const KURL & url)
{
load(url);
}
bool BookReader::queryExit()
{
writeSettings();
return true;
}
void BookReader::writeSettings()
{
KConfig * config = kapp->config();
config->writeEntry("size", m_view->size());
config->writeEntry("lastURL", m_view->currentURL());
config->writeEntry("lastURLPage", m_view->currentPage());
recentFilesAction->saveEntries(KGlobal::config());
}
void BookReader::readSettings()
{
recentFilesAction->loadEntries(KGlobal::config());
recentFilesAction->setEnabled(true); // force enabling
m_view->setParaOffset(Settings::paraOffset());
m_view->setEncodings(listEncodings());
m_view->setEncoding(Settings::defaultEncoding());
if (Settings::loadLastUrl())
{
loadLastUrl();
}
}
void BookReader::fullScreen()
{
if (m_fullScreenAction->isChecked())
{
menuBar()->hide();
setWindowState(windowState() | WindowFullScreen);
}
else
{
menuBar()->show();
setWindowState(windowState() & ~WindowFullScreen);
}
}
void BookReader::loadLastUrl()
{
KConfig * config = kapp->config();
TQSize size = config->readSizeEntry("size");
lastURL = config->readEntry("lastURL");
connect(m_view, TQT_SIGNAL(loadingFinished()), TQT_TQOBJECT(this), TQT_SLOT(loadLastURLSetPage()));
if (!lastURL.isEmpty())
{
// kdDebug() << "loadLastUrl: initial size = " << m_view->size() << endl;
m_view->resize(size);
// kdDebug() << "loadLastUrl: resize = " << m_view->size() << endl;
m_view->setupPageSize();
// kdDebug() << "render = 1" << endl;
load(lastURL);
}
}
void BookReader::loaded(int loaded)
{
//m_loaded = loaded;
m_splash->message(tqtr("Loading: %1 - %2%").tqarg(lastURL.fileName()).tqarg(loaded));
}
void BookReader::gotoFirstPage()
{
m_view->firstPage();
}
void BookReader::nextPage()
{
m_view->nextPage();
}
void BookReader::prevPage()
{
m_view->prevPage();
}
void BookReader::gotoLastPage( )
{
m_view->lastPage();
}
void BookReader::gotoPage()
{
bool isOk;
int page = KInputDialog::getInteger(tr("Goto page"), tr("Page number"),
m_view->currentPage(), 1,
m_view->pageCount(), 1, &isOk);
m_view->setCurrentPage(page - 1);
}
void BookReader::loadLastURLSetPage()
{
int lastURLPage = kapp->config()->readNumEntry("lastURLPage");
m_view->setCurrentPage(lastURLPage);
}
void BookReader::addBookmark()
{
bool isOk;
TQString name = KInputDialog::getText(tr("Add bookmark"),
tr("Bookmark name"), tr("Here"), &isOk);
if (isOk)
{
m_view->addBookmark(name);
updateBookmarks();
}
}
/*!
\fn BookReader::updateBookmarks()
*/
void BookReader::updateBookmarks()
{
unplugActionList("my_bookmarks");
m_bookmarkActions.clear();
m_bookmarkActions.setAutoDelete(true);
const Bookmarks & bms = m_view->bookmarks();
TQSignalMapper *bookmarkMapper = new TQSignalMapper(TQT_TQOBJECT(this));
connect(bookmarkMapper, TQT_SIGNAL(mapped(int)), TQT_TQOBJECT(this), TQT_SLOT(gotoBookmark(int)));
for (Bookmarks::size_type i = 0; i < 9 && i < bms.size(); ++i)
{
const Bookmark & bm = bms[i];
KAction * action = new KAction(bm.name(), ALT+Key_1 + i);
connect(action, TQT_SIGNAL(activated()), bookmarkMapper, TQT_SLOT(map()));
m_bookmarkActions.append(action);
bookmarkMapper->setMapping(action, i);
}
plugActionList("my_bookmarks", m_bookmarkActions);
}
/*!
\fn BookReader::gotoBookmark(int index)
*/
void BookReader::gotoBookmark(int index)
{
const Bookmarks & bms = m_view->bookmarks();
assert(index < bms.size());
unsigned int page = bms[index].page();
m_view->setCurrentPage(page);
}
/*!
\fn BookReader::editBookmarks()
*/
void BookReader::editBookmarks()
{
/// @todo implement me
BookmarksDlg dialog(m_view->bookmarks());
if (dialog.exec() == TQDialog::Accepted)
{
m_view->setBookmarks(dialog.bookmarks());
updateBookmarks();
}
}
#include "bookreader.moc"