4 #include <QApplication>
9 # include <QtMaemo5/QMaemo5InformationBox>
11 # include <mce/mode-names.h>
12 # include <mce/dbus-names.h>
13 #endif // Q_WS_MAEMO_5
18 #include "infodialog.h"
19 #include "librarydialog.h"
21 #include "mainwindow.h"
22 #include "settingswindow.h"
23 #include "bookmarksdialog.h"
25 #include "chaptersdialog.h"
26 #include "fullscreenwindow.h"
28 #include "bookfinder.h"
30 #ifdef DORIAN_TEST_MODEL
31 #include "modeltest.h"
35 # define ICON_PREFIX ":/icons/mac/"
37 # define ICON_PREFIX ":/icons/"
40 MainWindow::MainWindow(QWidget *parent):
41 QMainWindow(parent), view(0), preventBlankingTimer(-1)
43 Trace t("MainWindow::MainWindow");
45 setAttribute(Qt::WA_Maemo5StackedWindow, true);
47 setWindowTitle("Dorian");
49 // Central widget. Must be an intermediate, because the book view widget
50 // can be re-parented later
51 QFrame *central = new QFrame(this);
52 QVBoxLayout *layout = new QVBoxLayout(central);
54 central->setLayout(layout);
55 setCentralWidget(central);
58 view = new BookView(central);
60 layout->addWidget(view);
63 setUnifiedTitleAndToolBarOnMac(true);
64 settings = new QDialog(this);
65 toolBar = addToolBar("controls");
66 toolBar->setMovable(false);
67 toolBar->setFloatable(false);
68 toolBar->toggleViewAction()->setVisible(false);
69 #if defined(Q_WS_X11) && !defined(Q_WS_MAEMO_5)
70 toolBar->setIconSize(QSize(42, 42));
73 previousAction = addToolBarAction(view, SLOT(goPrevious()), "previous");
74 nextAction = addToolBarAction(view, SLOT(goNext()), "next");
75 chaptersAction = addToolBarAction(this, SLOT(showChapters()), "chapters");
76 bookmarksAction = addToolBarAction(this, SLOT(showBookmarks()), "bookmarks");
79 infoAction = menuBar()->addAction(tr("Book details"));
80 connect(infoAction, SIGNAL(triggered()), this, SLOT(showInfo()));
81 libraryAction = menuBar()->addAction(tr("Library"));
82 connect(libraryAction, SIGNAL(triggered()), this, SLOT(showLibrary()));
83 settingsAction = menuBar()->addAction(tr("Settings"));
84 connect(settingsAction, SIGNAL(triggered()), this, SLOT(showSettings()));
85 devToolsAction = menuBar()->addAction(tr("Developer"));
86 connect(devToolsAction, SIGNAL(triggered()), this, SLOT(showDevTools()));
88 infoAction = addToolBarAction(this, SLOT(showInfo()), "document-properties");
89 libraryAction = addToolBarAction(this, SLOT(showLibrary()),
90 "system-file-manager");
91 settingsAction = addToolBarAction(this, SLOT(showSettings()),
92 "preferences-system");
93 devToolsAction = addToolBarAction(this, SLOT(showDevTools()), "developer");
94 #endif // Q_WS_MAEMO_5
96 QFrame *frame = new QFrame(toolBar);
97 frame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
98 toolBar->addWidget(frame);
100 fullScreenAction = addToolBarAction(this, SLOT(showBig()), "view-fullscreen");
102 // Handle model changes
103 connect(Library::instance(), SIGNAL(nowReadingChanged()),
104 this, SLOT(onCurrentBookChanged()));
106 // Load book on command line, or load last read book, or load default book
107 Library *library = Library::instance();
108 if (QCoreApplication::arguments().size() == 2) {
109 QString path = QCoreApplication::arguments()[1];
111 QModelIndex index = library->find(path);
112 if (index.isValid()) {
113 library->setNowReading(index);
117 QModelIndex index = library->nowReading();
118 if (index.isValid()) {
119 library->setNowReading(index);
122 if (!library->rowCount()) {
123 library->add(":/books/2 B R 0 2 B.epub");
125 library->setNowReading(library->index(0));
129 // Handle settings changes
130 Settings *settings = Settings::instance();
131 connect(settings, SIGNAL(valueChanged(const QString &)),
132 this, SLOT(onSettingsChanged(const QString &)));
133 settings->setValue("orientation", settings->value("orientation"));
134 settings->setValue("lightson", settings->value("lightson"));
136 // Handle loading chapters
137 connect(view, SIGNAL(chapterLoadStart(int)),
138 this, SLOT(onChapterLoadStart()));
139 connect(view, SIGNAL(chapterLoadEnd(int)),
140 this, SLOT(onChapterLoadEnd(int)));
142 // Shadow window for full screen
143 fullScreenWindow = new FullScreenWindow(this);
144 connect(fullScreenWindow, SIGNAL(restore()), this, SLOT(showRegular()));
146 // Create thread for finding books in directories
147 bookFinder = new BookFinder();
148 connect(bookFinder, SIGNAL(add(const QString &)),
149 library, SLOT(add(const QString &)));
150 connect(bookFinder, SIGNAL(remove(const QString &)),
151 library, SLOT(remove(const QString &)));
152 bookFinder->moveToThread(&bookFinderThread);
153 bookFinderThread.start();
156 bool ret = QMetaObject::invokeMethod(
159 Q_ARG(QStringList, QStringList(QString("/Users/polster/Books"))),
160 Q_ARG(QStringList, library->bookPaths()));
161 t.trace(QString("Invoking BookFinder::find ") + (ret?"succeeded":"failed"));
164 #ifdef DORIAN_TEST_MODEL
165 (void)new ModelTest(Library::instance(), this);
169 MainWindow::~MainWindow()
171 bookFinderThread.quit();
172 bookFinderThread.wait();
176 void MainWindow::onCurrentBookChanged()
178 setCurrentBook(Library::instance()->nowReading());
181 void MainWindow::showRegular()
183 Trace t("MainWindow::showRegular");
184 fullScreenWindow->hide();
185 fullScreenWindow->leaveChild();
186 view->setParent(centralWidget());
187 centralWidget()->layout()->addWidget(view);
190 void MainWindow::showBig()
192 Trace t("MainWindow::showBig");
193 centralWidget()->layout()->removeWidget(view);
194 fullScreenWindow->takeChild(view);
195 fullScreenWindow->showFullScreen();
198 void MainWindow::setCurrentBook(const QModelIndex ¤t)
201 Book *book = Library::instance()->book(current);
203 setWindowTitle(book? book->shortName(): tr("Dorian"));
206 QAction *MainWindow::addToolBarAction(const QObject *receiver,
211 addAction(QIcon(ICON_PREFIX + name + ".png"), "", receiver, member);
214 void MainWindow::showLibrary()
216 (new LibraryDialog(this))->show();
219 void MainWindow::showSettings()
221 (new SettingsWindow(this))->show();
224 void MainWindow::showInfo()
226 if (mCurrent.isValid()) {
227 (new InfoDialog(Library::instance()->book(mCurrent), this))->exec();
231 void MainWindow::showDevTools()
233 (new DevTools())->exec();
236 void MainWindow::showBookmarks()
238 Book *book = Library::instance()->book(mCurrent);
240 BookmarksDialog *bookmarks = new BookmarksDialog(book, this);
241 bookmarks->setWindowModality(Qt::WindowModal);
242 connect(bookmarks, SIGNAL(addBookmark()), this, SLOT(onAddBookmark()));
243 connect(bookmarks, SIGNAL(goToBookmark(int)),
244 this, SLOT(onGoToBookmark(int)));
249 void MainWindow::closeEvent(QCloseEvent *event)
251 Trace t("MainWindow::closeEvent");
252 view->setLastBookmark();
256 void MainWindow::onSettingsChanged(const QString &key)
259 if (key == "orientation") {
260 QString value = Settings::instance()->value(key).toString();
261 Trace::trace(QString("MainWindow::onSettingsChanged: orientation %1").
263 if (value == "portrait") {
264 setAttribute(Qt::WA_Maemo5LandscapeOrientation, false);
265 setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
268 setAttribute(Qt::WA_Maemo5PortraitOrientation, false);
269 setAttribute(Qt::WA_Maemo5LandscapeOrientation, true);
271 } else if (key == "lightson") {
272 bool enable = Settings::instance()->value(key, false).toBool();
273 Trace::trace(QString("MainWindow::onSettingsChanged: lightson: %1").
275 killTimer(preventBlankingTimer);
277 preventBlankingTimer = startTimer(29 * 1000);
282 #endif // Q_WS_MAEMO_5
285 void MainWindow::onChapterLoadStart()
287 Trace t("MainWindow::onChapterLoadStart");
289 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, true);
293 void MainWindow::onChapterLoadEnd(int index)
295 Trace t("MainWindow::onChapterLoadEnd");
296 bool enablePrevious = false;
297 bool enableNext = false;
298 Book *book = Library::instance()->book(mCurrent);
301 enablePrevious = true;
303 if (index < (book->toc.size() - 1)) {
308 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, false);
309 previousAction->setIcon(QIcon(enablePrevious?
310 ":/icons/previous.png" : ":/icons/previous-disabled.png"));
311 nextAction->setIcon(QIcon(enableNext?
312 ":/icons/next.png": ":/icons/next-disabled.png"));
313 #endif // Q_WS_MAEMO_5
314 previousAction->setEnabled(enablePrevious);
315 nextAction->setEnabled(enableNext);
318 void MainWindow::onAddBookmark()
320 Trace t("MainWindow:onAddBookmark");
324 void MainWindow::onGoToBookmark(int index)
326 Trace t("MainWindow::onGoToBookmark");
327 Book *book = Library::instance()->book(mCurrent);
328 view->goToBookmark(book->bookmarks()[index]);
331 void MainWindow::showChapters()
333 Book *book = Library::instance()->book(mCurrent);
335 ChaptersDialog *chapters = new ChaptersDialog(book, this);
336 chapters->setWindowModality(Qt::WindowModal);
337 connect(chapters, SIGNAL(goToChapter(int)),
338 this, SLOT(onGoToChapter(int)));
343 void MainWindow::onGoToChapter(int index)
345 Trace t("MainWindow::onGoToChapter");
347 Book *book = Library::instance()->book(mCurrent);
349 t.trace("No current book?");
353 QString id = book->chapters[index];
354 QString href = book->content[id].href;
355 QString baseRef(href);
356 QUrl url(QString("file://") + href);
357 if (url.hasFragment()) {
358 QString fragment = url.fragment();
359 baseRef.chop(fragment.length() + 1);
362 // Swipe through all content items to find the one matching the chapter href
363 // FIXME: Do we need to index content items by href, too?
366 foreach (contentKey, book->content.keys()) {
367 if (contentKey == id) {
370 if (book->content[contentKey].href == baseRef) {
372 t.trace(QString("Key for %1 is %2").arg(baseRef).arg(contentKey));
377 t.trace("Could not find key for " + baseRef);
381 int tocIndex = book->toc.indexOf(contentKey);
382 if (tocIndex != -1) {
383 view->goToBookmark(Book::Bookmark(tocIndex, 0));
385 qCritical() << "Could not find toc index of chapter" << id;
389 void MainWindow::timerEvent(QTimerEvent *event)
391 if (event->timerId() == preventBlankingTimer) {
393 QDBusInterface mce(MCE_SERVICE, MCE_REQUEST_PATH,
394 MCE_REQUEST_IF, QDBusConnection::systemBus());
395 mce.call(MCE_PREVENT_BLANK_REQ);
396 #endif // Q_WS_MAEMO_5
397 Trace::trace("MainWindow::timerEvent: Prevent display blanking");