/*************************************************************************** copyright : (C) 2001-2006 by Robby Stephenson email : robby@periapsis.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of version 2 of the GNU General Public License as * * published by the Free Software Foundation; * * * ***************************************************************************/ #include "mainwindow.h" #include "tellico_kernel.h" #include "document.h" #include "detailedlistview.h" #include "entryeditdialog.h" #include "groupview.h" #include "viewstack.h" #include "collection.h" #include "entry.h" #include "configdialog.h" #include "entryitem.h" #include "filter.h" #include "filterdialog.h" #include "collectionfieldsdialog.h" #include "controller.h" #include "importdialog.h" #include "exportdialog.h" #include "filehandler.h" // needed so static mainWindow variable can be set #include "gui/stringmapdialog.h" #include "translators/htmlexporter.h" // for printing #include "entryview.h" #include "entryiconview.h" #include "imagefactory.h" // needed so tmp files can get cleaned #include "collections/bibtexcollection.h" // needed for bibtex string macro dialog #include "translators/bibtexhandler.h" // needed for bibtex options #include "fetchdialog.h" #include "reportdialog.h" #include "tellico_strings.h" #include "filterview.h" #include "loanview.h" #include "gui/tabcontrol.h" #include "gui/lineedit.h" #include "tellico_utils.h" #include "tellico_debug.h" #include "entryiconfactory.h" #include "statusbar.h" #include "fetch/fetchmanager.h" #include "cite/actionmanager.h" #include "core/tellico_config.h" #include "core/drophandler.h" #include "latin1literal.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include // needed for copy, cut, paste slots #include #include // the null string and bool are dummy arguments #define MIME_ICON(s) \ KMimeType::mimeType(TQString::fromLatin1(s))->icon(TQString(), false) namespace { static const int MAIN_WINDOW_MIN_WIDTH = 600; //static const int PRINTED_PAGE_OVERLAP = 0; static const int MAX_IMAGES_WARN_PERFORMANCE = 200; } using Tellico::MainWindow; MainWindow::MainWindow(TQWidget* parent_/*=0*/, const char* name_/*=0*/) : TDEMainWindow(parent_, name_), ApplicationInterface(), m_updateAll(0), m_statusBar(0), m_editDialog(0), m_groupView(0), m_filterView(0), m_loanView(0), m_configDlg(0), m_filterDlg(0), m_collFieldsDlg(0), m_stringMacroDlg(0), m_fetchDlg(0), m_reportDlg(0), m_queuedFilters(0), m_initialized(false), m_newDocument(true) { if(!kapp->dcopClient()->isRegistered()) { kapp->dcopClient()->registerAs("tellico"); kapp->dcopClient()->setDefaultObject(objId()); } m_fetchActions.setAutoDelete(true); // these are the fetcher actions Controller::init(this); // the only time this is ever called! // has to be after controller init Kernel::init(this); // the only time this is ever called! setIcon(DesktopIcon(TQString::fromLatin1("tellico"))); // initialize the status bar and progress bar initStatusBar(); // create a document, which also creates an empty book collection // must be done before the different widgets are created initDocument(); // set up all the actions, some connect to the document, so this must be after initDocument() initActions(); // create the different widgets in the view, some widgets connect to actions, so must be after initActions() initView(); // The edit dialog is not created until after the main window is initialized, so it can be a child. // So don't make any connections, don't read options for it until initFileOpen readOptions(); setAcceptDrops(true); DropHandler* drophandler = new DropHandler(TQT_TQOBJECT(this)); installEventFilter(drophandler); MARK_LINE; TQTimer::singleShot(0, TQT_TQOBJECT(this), TQT_SLOT(slotInit())); } void MainWindow::slotInit() { MARK; if(m_editDialog) { return; } m_editDialog = new EntryEditDialog(this, "editdialog"); Controller::self()->addObserver(m_editDialog); m_toggleEntryEditor->setChecked(Config::showEditWidget()); slotToggleEntryEditor(); initConnections(); ImageFactory::init(); // disable OOO menu item if library is not available action("cite_openoffice")->setEnabled(Cite::ActionManager::isEnabled(Cite::CiteOpenOffice)); } void MainWindow::initStatusBar() { MARK; m_statusBar = new Tellico::StatusBar(this); } void MainWindow::initActions() { MARK; /************************************************* * File->New menu *************************************************/ TQSignalMapper* collectionMapper = new TQSignalMapper(TQT_TQOBJECT(this)); connect(collectionMapper, TQT_SIGNAL(mapped(int)), TQT_TQOBJECT(this), TQT_SLOT(slotFileNew(int))); TDEActionMenu* fileNewMenu = new TDEActionMenu(actionCollection(), "file_new_collection"); fileNewMenu->setText(i18n("New")); // fileNewMenu->setIconSet(BarIconSet(TQString::fromLatin1("filenew"))); // doesn't work fileNewMenu->setIconSet(BarIcon(TQString::fromLatin1("filenew"))); fileNewMenu->setToolTip(i18n("Create a new collection")); fileNewMenu->setDelayed(false); TDEAction* action = new TDEAction(actionCollection(), "new_book_collection"); action->setText(i18n("New &Book Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("book"))); action->setToolTip(i18n("Create a new book collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Book); action = new TDEAction(actionCollection(), "new_bibtex_collection"); action->setText(i18n("New B&ibliography")); action->setIconSet(UserIconSet(TQString::fromLatin1("bibtex"))); action->setToolTip(i18n("Create a new bibtex bibliography")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Bibtex); action = new TDEAction(actionCollection(), "new_comic_book_collection"); action->setText(i18n("New &Comic Book Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("comic"))); action->setToolTip(i18n("Create a new comic book collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::ComicBook); action = new TDEAction(actionCollection(), "new_video_collection"); action->setText(i18n("New &Video Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("video"))); action->setToolTip(i18n("Create a new video collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Video); action = new TDEAction(actionCollection(), "new_music_collection"); action->setText(i18n("New &Music Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("album"))); action->setToolTip(i18n("Create a new music collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Album); action = new TDEAction(actionCollection(), "new_coin_collection"); action->setText(i18n("New C&oin Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("coin"))); action->setToolTip(i18n("Create a new coin collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Coin); action = new TDEAction(actionCollection(), "new_stamp_collection"); action->setText(i18n("New &Stamp Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("stamp"))); action->setToolTip(i18n("Create a new stamp collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Stamp); action = new TDEAction(actionCollection(), "new_card_collection"); action->setText(i18n("New C&ard Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("card"))); action->setToolTip(i18n("Create a new trading card collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Card); action = new TDEAction(actionCollection(), "new_wine_collection"); action->setText(i18n("New &Wine Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("wine"))); action->setToolTip(i18n("Create a new wine collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Wine); action = new TDEAction(actionCollection(), "new_game_collection"); action->setText(i18n("New &Game Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("game"))); action->setToolTip(i18n("Create a new game collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Game); action = new TDEAction(actionCollection(), "new_boardgame_collection"); action->setText(i18n("New Boa&rd Game Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("boardgame"))); action->setToolTip(i18n("Create a new board game collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::BoardGame); action = new TDEAction(actionCollection(), "new_file_catalog"); action->setText(i18n("New &File Catalog")); action->setIconSet(UserIconSet(TQString::fromLatin1("file"))); action->setToolTip(i18n("Create a new file catalog")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::File); action = new TDEAction(actionCollection(), "new_custom_collection"); action->setText(i18n("New C&ustom Collection")); action->setIconSet(UserIconSet(TQString::fromLatin1("filenew"))); action->setToolTip(i18n("Create a new custom collection")); fileNewMenu->insert(action); connect(action, TQT_SIGNAL(activated()), collectionMapper, TQT_SLOT(map())); collectionMapper->setMapping(action, Data::Collection::Base); /************************************************* * File menu *************************************************/ action = KStdAction::open(TQT_TQOBJECT(this), TQT_SLOT(slotFileOpen()), actionCollection()); action->setToolTip(i18n("Open an existing document")); m_fileOpenRecent = KStdAction::openRecent(TQT_TQOBJECT(this), TQT_SLOT(slotFileOpenRecent(const KURL&)), actionCollection()); m_fileOpenRecent->setToolTip(i18n("Open a recently used file")); m_fileSave = KStdAction::save(TQT_TQOBJECT(this), TQT_SLOT(slotFileSave()), actionCollection()); m_fileSave->setToolTip(i18n("Save the document")); action = KStdAction::saveAs(TQT_TQOBJECT(this), TQT_SLOT(slotFileSaveAs()), actionCollection()); action->setToolTip(i18n("Save the document as a different file...")); action = KStdAction::print(TQT_TQOBJECT(this), TQT_SLOT(slotFilePrint()), actionCollection()); action->setToolTip(i18n("Print the contents of the document...")); action = KStdAction::quit(TQT_TQOBJECT(this), TQT_SLOT(slotFileQuit()), actionCollection()); action->setToolTip(i18n("Quit the application")); /**************** Import Menu ***************************/ TQSignalMapper* importMapper = new TQSignalMapper(TQT_TQOBJECT(this)); connect(importMapper, TQT_SIGNAL(mapped(int)), TQT_TQOBJECT(this), TQT_SLOT(slotFileImport(int))); TDEActionMenu* importMenu = new TDEActionMenu(actionCollection(), "file_import"); importMenu->setText(i18n("&Import")); importMenu->setIconSet(BarIconSet(TQString::fromLatin1("fileimport"))); importMenu->setToolTip(i18n("Import collection data from other formats")); importMenu->setDelayed(false); action = new TDEAction(actionCollection(), "file_import_tellico"); action->setText(i18n("Import Tellico Data...")); action->setToolTip(i18n("Import another Tellico data file")); action->setIcon(TQString::fromLatin1("tellico")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::TellicoXML); action = new TDEAction(actionCollection(), "file_import_csv"); action->setText(i18n("Import CSV Data...")); action->setToolTip(i18n("Import a CSV file")); action->setIcon(MIME_ICON("text/csv")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::CSV); action = new TDEAction(actionCollection(), "file_import_mods"); action->setText(i18n("Import MODS Data...")); action->setToolTip(i18n("Import a MODS data file")); action->setIcon(MIME_ICON("text/xml")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::MODS); action = new TDEAction(actionCollection(), "file_import_alexandria"); action->setText(i18n("Import Alexandria Data...")); action->setToolTip(i18n("Import data from the Alexandria book collection manager")); action->setIcon(TQString::fromLatin1("alexandria")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::Alexandria); action = new TDEAction(actionCollection(), "file_import_delicious"); action->setText(i18n("Import Delicious Library Data...")); action->setToolTip(i18n("Import data from Delicious Library")); action->setIcon(MIME_ICON("text/xml")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::Delicious); action = new TDEAction(actionCollection(), "file_import_referencer"); action->setText(i18n("Import Referencer Data...")); action->setToolTip(i18n("Import data from Referencer")); action->setIcon(TQString::fromLatin1("referencer")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::Referencer); action = new TDEAction(actionCollection(), "file_import_bibtex"); action->setText(i18n("Import Bibtex Data...")); action->setToolTip(i18n("Import a bibtex bibliography file")); action->setIcon(MIME_ICON("text/x-bibtex")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::Bibtex); action = new TDEAction(actionCollection(), "file_import_bibtexml"); action->setText(i18n("Import Bibtexml Data...")); action->setToolTip(i18n("Import a Bibtexml bibliography file")); action->setIcon(MIME_ICON("text/xml")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::Bibtexml); action = new TDEAction(actionCollection(), "file_import_ris"); action->setText(i18n("Import RIS Data...")); action->setToolTip(i18n("Import an RIS reference file")); action->setIcon(MIME_ICON("application/x-research-info-systems")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::RIS); action = new TDEAction(actionCollection(), "file_import_pdf"); action->setText(i18n("Import PDF File...")); action->setToolTip(i18n("Import a PDF file")); action->setIcon(MIME_ICON("application/pdf")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::PDF); action = new TDEAction(actionCollection(), "file_import_audiofile"); action->setText(i18n("Import Audio File Metadata...")); action->setToolTip(i18n("Import meta-data from audio files")); action->setIcon(MIME_ICON("audio/x-mp3")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::AudioFile); #ifndef HAVE_TAGLIB action->setEnabled(false); #endif action = new TDEAction(actionCollection(), "file_import_freedb"); action->setText(i18n("Import Audio CD Data...")); action->setToolTip(i18n("Import audio CD information")); action->setIcon(MIME_ICON("media/audiocd")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::FreeDB); #ifndef HAVE_KCDDB action->setEnabled(false); #endif action = new TDEAction(actionCollection(), "file_import_gcfilms"); action->setText(i18n("Import GCstar Data...")); action->setToolTip(i18n("Import a GCstar data file")); action->setIcon(TQString::fromLatin1("gcstar")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::GCfilms); action = new TDEAction(actionCollection(), "file_import_griffith"); action->setText(i18n("Import Griffith Data...")); action->setToolTip(i18n("Import a Griffith database")); action->setIcon(TQString::fromLatin1("griffith")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::Griffith); action = new TDEAction(actionCollection(), "file_import_amc"); action->setText(i18n("Import Ant Movie Catalog Data...")); action->setToolTip(i18n("Import an Ant Movie Catalog data file")); action->setIcon(MIME_ICON("application/x-crossover-amc")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::AMC); action = new TDEAction(actionCollection(), "file_import_filelisting"); action->setText(i18n("Import File Listing...")); action->setToolTip(i18n("Import information about files in a folder")); action->setIcon(MIME_ICON("inode/directory")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::FileListing); action = new TDEAction(actionCollection(), "file_import_xslt"); action->setText(i18n("Import XSL Transform...")); action->setToolTip(i18n("Import using an XSL Transform")); action->setIcon(MIME_ICON("text/x-xslt")); importMenu->insert(action); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); importMapper->setMapping(action, Import::XSLT); /**************** Export Menu ***************************/ TQSignalMapper* exportMapper = new TQSignalMapper(TQT_TQOBJECT(this)); connect(exportMapper, TQT_SIGNAL(mapped(int)), TQT_TQOBJECT(this), TQT_SLOT(slotFileExport(int))); TDEActionMenu* exportMenu = new TDEActionMenu(actionCollection(), "file_export"); exportMenu->setText(i18n("&Export")); exportMenu->setIconSet(BarIconSet(TQString::fromLatin1("fileexport"))); exportMenu->setToolTip(i18n("Export the collection data to other formats")); exportMenu->setDelayed(false); action = new TDEAction(actionCollection(), "file_export_xml"); action->setText(i18n("Export to XML...")); action->setToolTip(i18n("Export to a Tellico XML file")); action->setIcon(TQString::fromLatin1("tellico")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::TellicoXML); action = new TDEAction(actionCollection(), "file_export_zip"); action->setText(i18n("Export to Zip...")); action->setToolTip(i18n("Export to a Tellico Zip file")); action->setIcon(TQString::fromLatin1("tellico")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::TellicoZip); action = new TDEAction(actionCollection(), "file_export_html"); action->setText(i18n("Export to HTML...")); action->setToolTip(i18n("Export to an HTML file")); action->setIcon(MIME_ICON("text/html")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::HTML); action = new TDEAction(actionCollection(), "file_export_csv"); action->setText(i18n("Export to CSV...")); action->setToolTip(i18n("Export to a comma-separated values file")); action->setIcon(MIME_ICON("text/csv")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::CSV); action = new TDEAction(actionCollection(), "file_export_pilotdb"); action->setText(i18n("Export to PilotDB...")); action->setToolTip(i18n("Export to a PilotDB database")); action->setIcon(MIME_ICON("application/vnd.palm")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::PilotDB); action = new TDEAction(actionCollection(), "file_export_alexandria"); action->setText(i18n("Export to Alexandria...")); action->setToolTip(i18n("Export to an Alexandria library")); action->setIcon(TQString::fromLatin1("alexandria")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::Alexandria); action = new TDEAction(actionCollection(), "file_export_bibtex"); action->setText(i18n("Export to Bibtex...")); action->setToolTip(i18n("Export to a bibtex file")); action->setIcon(MIME_ICON("text/x-bibtex")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::Bibtex); action = new TDEAction(actionCollection(), "file_export_bibtexml"); action->setText(i18n("Export to Bibtexml...")); action->setToolTip(i18n("Export to a Bibtexml file")); action->setIcon(MIME_ICON("text/xml")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::Bibtexml); action = new TDEAction(actionCollection(), "file_export_onix"); action->setText(i18n("Export to ONIX...")); action->setToolTip(i18n("Export to an ONIX file")); action->setIcon(MIME_ICON("text/xml")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::ONIX); action = new TDEAction(actionCollection(), "file_export_gcfilms"); action->setText(i18n("Export to GCfilms...")); action->setToolTip(i18n("Export to a GCfilms data file")); action->setIcon(TQString::fromLatin1("gcstar")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::GCfilms); #if 0 TQString dummy1 = i18n("Export to GCstar..."); TQString dummy2 = i18n("Export to a GCstar data file"); #endif action = new TDEAction(actionCollection(), "file_export_xslt"); action->setText(i18n("Export XSL Transform...")); action->setToolTip(i18n("Export using an XSL Transform")); action->setIcon(MIME_ICON("text/x-xslt")); exportMenu->insert(action); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); exportMapper->setMapping(action, Export::XSLT); /************************************************* * Edit menu *************************************************/ action = KStdAction::cut(TQT_TQOBJECT(this), TQT_SLOT(slotEditCut()), actionCollection()); action->setToolTip(i18n("Cut the selected text and puts it in the clipboard")); action = KStdAction::copy(TQT_TQOBJECT(this), TQT_SLOT(slotEditCopy()), actionCollection()); action->setToolTip(i18n("Copy the selected text to the clipboard")); action = KStdAction::paste(TQT_TQOBJECT(this), TQT_SLOT(slotEditPaste()), actionCollection()); action->setToolTip(i18n("Paste the clipboard contents")); action = KStdAction::selectAll(TQT_TQOBJECT(this), TQT_SLOT(slotEditSelectAll()), actionCollection()); action->setToolTip(i18n("Select all the entries in the collection")); action = KStdAction::deselect(TQT_TQOBJECT(this), TQT_SLOT(slotEditDeselect()), actionCollection()); action->setToolTip(i18n("Deselect all the entries in the collection")); action = new TDEAction(i18n("Internet Search..."), TQString::fromLatin1("wizard"), CTRL + Key_M, TQT_TQOBJECT(this), TQT_SLOT(slotShowFetchDialog()), actionCollection(), "edit_search_internet"); action->setToolTip(i18n("Search the internet...")); action = new TDEAction(i18n("Advanced &Filter..."), TQString::fromLatin1("filter"), CTRL + Key_J, TQT_TQOBJECT(this), TQT_SLOT(slotShowFilterDialog()), actionCollection(), "filter_dialog"); action->setToolTip(i18n("Filter the collection")); /************************************************* * Collection menu *************************************************/ m_newEntry = new TDEAction(i18n("&New Entry..."), TQString::fromLatin1("filenew"), CTRL + Key_N, TQT_TQOBJECT(this), TQT_SLOT(slotNewEntry()), actionCollection(), "coll_new_entry"); m_newEntry->setToolTip(i18n("Create a new entry")); m_editEntry = new TDEAction(i18n("&Edit Entry..."), TQString::fromLatin1("edit"), CTRL + Key_E, TQT_TQOBJECT(this), TQT_SLOT(slotShowEntryEditor()), actionCollection(), "coll_edit_entry"); m_editEntry->setToolTip(i18n("Edit the selected entries")); m_copyEntry = new TDEAction(i18n("D&uplicate Entry"), TQString::fromLatin1("editcopy"), CTRL + Key_Y, Controller::self(), TQT_SLOT(slotCopySelectedEntries()), actionCollection(), "coll_copy_entry"); m_copyEntry->setToolTip(i18n("Copy the selected entries")); m_deleteEntry = new TDEAction(i18n("&Delete Entry"), TQString::fromLatin1("editdelete"), CTRL + Key_D, Controller::self(), TQT_SLOT(slotDeleteSelectedEntries()), actionCollection(), "coll_delete_entry"); m_deleteEntry->setToolTip(i18n("Delete the selected entries")); m_mergeEntry = new TDEAction(i18n("&Merge Entries"), TQString::fromLatin1("editcopy"), CTRL + Key_G, Controller::self(), TQT_SLOT(slotMergeSelectedEntries()), actionCollection(), "coll_merge_entry"); m_mergeEntry->setToolTip(i18n("Merge the selected entries")); m_mergeEntry->setEnabled(false); // gets enabled when more than 1 entry is selected action = new TDEAction(i18n("&Generate Reports..."), TQString::fromLatin1("document"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotShowReportDialog()), actionCollection(), "coll_reports"); action->setToolTip(i18n("Generate collection reports")); m_checkOutEntry = new TDEAction(i18n("Check-&out..."), TQString::fromLatin1("2uparrow"), 0, Controller::self(), TQT_SLOT(slotCheckOut()), actionCollection(), "coll_checkout"); m_checkOutEntry->setToolTip(i18n("Check-out the selected items")); m_checkInEntry = new TDEAction(i18n("Check-&in"), TQString::fromLatin1("2downarrow"), 0, Controller::self(), TQT_SLOT(slotCheckIn()), actionCollection(), "coll_checkin"); m_checkInEntry->setToolTip(i18n("Check-in the selected items")); action = new TDEAction(i18n("&Rename Collection..."), TQString::fromLatin1("editclear"), CTRL + Key_R, TQT_TQOBJECT(this), TQT_SLOT(slotRenameCollection()), actionCollection(), "coll_rename_collection"); action->setToolTip(i18n("Rename the collection")); action = new TDEAction(i18n("Collection &Fields..."), TQString::fromLatin1("edit"), CTRL + Key_U, TQT_TQOBJECT(this), TQT_SLOT(slotShowCollectionFieldsDialog()), actionCollection(), "coll_fields"); action->setToolTip(i18n("Modify the collection fields")); action = new TDEAction(i18n("Convert to &Bibliography"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotConvertToBibliography()), actionCollection(), "coll_convert_bibliography"); action->setToolTip(i18n("Convert a book collection to a bibliography")); action->setIconSet(UserIconSet(TQString::fromLatin1("bibtex"))); action = new TDEAction(i18n("String &Macros..."), TQString::fromLatin1("view_text"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotShowStringMacroDialog()), actionCollection(), "coll_string_macros"); action->setToolTip(i18n("Edit the bibtex string macros")); TQSignalMapper* citeMapper = new TQSignalMapper(TQT_TQOBJECT(this)); connect(citeMapper, TQT_SIGNAL(mapped(int)), TQT_TQOBJECT(this), TQT_SLOT(slotCiteEntry(int))); action = new TDEAction(actionCollection(), "cite_clipboard"); action->setText(i18n("Copy Bibtex to Cli&pboard")); action->setToolTip(i18n("Copy bibtex citations to the clipboard")); action->setIcon(TQString::fromLatin1("editpaste")); connect(action, TQT_SIGNAL(activated()), citeMapper, TQT_SLOT(map())); citeMapper->setMapping(action, Cite::CiteClipboard); action = new TDEAction(actionCollection(), "cite_lyxpipe"); action->setText(i18n("Cite Entry in &LyX")); action->setToolTip(i18n("Cite the selected entries in LyX")); action->setIcon(TQString::fromLatin1("lyx")); connect(action, TQT_SIGNAL(activated()), citeMapper, TQT_SLOT(map())); citeMapper->setMapping(action, Cite::CiteLyxpipe); action = new TDEAction(actionCollection(), "cite_openoffice"); action->setText(i18n("Ci&te Entry in OpenOffice.org")); action->setToolTip(i18n("Cite the selected entries in OpenOffice.org")); action->setIcon(TQString::fromLatin1("ooo-writer")); connect(action, TQT_SIGNAL(activated()), citeMapper, TQT_SLOT(map())); citeMapper->setMapping(action, Cite::CiteOpenOffice); TQSignalMapper* updateMapper = new TQSignalMapper(TQT_TQOBJECT(this), "update_mapper"); connect(updateMapper, TQT_SIGNAL(mapped(const TQString&)), Controller::self(), TQT_SLOT(slotUpdateSelectedEntries(const TQString&))); m_updateEntryMenu = new TDEActionMenu(i18n("&Update Entry"), actionCollection(), "coll_update_entry"); // m_updateEntryMenu->setIconSet(BarIconSet(TQString::fromLatin1("fileexport"))); m_updateEntryMenu->setDelayed(false); m_updateAll = new TDEAction(actionCollection(), "update_entry_all"); m_updateAll->setText(i18n("All Sources")); m_updateAll->setToolTip(i18n("Update entry data from all available sources")); // m_updateEntryMenu->insert(action); connect(m_updateAll, TQT_SIGNAL(activated()), updateMapper, TQT_SLOT(map())); updateMapper->setMapping(m_updateAll, TQString::fromLatin1("_all")); /************************************************* * Settings menu *************************************************/ setStandardToolBarMenuEnabled(true); createStandardStatusBarAction(); KStdAction::configureToolbars(TQT_TQOBJECT(this), TQT_SLOT(slotConfigToolbar()), actionCollection()); KStdAction::keyBindings(TQT_TQOBJECT(this), TQT_SLOT(slotConfigKeys()), actionCollection()); m_toggleGroupWidget = new TDEToggleAction(i18n("Show Grou&p View"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotToggleGroupWidget()), actionCollection(), "toggle_group_widget"); m_toggleGroupWidget->setToolTip(i18n("Enable/disable the group view")); m_toggleGroupWidget->setCheckedState(i18n("Hide Grou&p View")); m_toggleEntryEditor = new TDEToggleAction(i18n("Show Entry &Editor"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotToggleEntryEditor()), actionCollection(), "toggle_edit_widget"); m_toggleEntryEditor->setToolTip(i18n("Enable/disable the editor")); m_toggleEntryEditor->setCheckedState(i18n("Hide Entry &Editor")); m_toggleEntryView = new TDEToggleAction(i18n("Show Entry &View"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotToggleEntryView()), actionCollection(), "toggle_entry_view"); m_toggleEntryView->setToolTip(i18n("Enable/disable the entry view")); m_toggleEntryView->setCheckedState(i18n("Hide Entry &View")); KStdAction::preferences(TQT_TQOBJECT(this), TQT_SLOT(slotShowConfigDialog()), actionCollection()); /************************************************* * Help menu *************************************************/ KStdAction::tipOfDay(TQT_TQOBJECT(this), TQT_SLOT(slotShowTipOfDay()), actionCollection(), "tipOfDay"); /************************************************* * Collection Toolbar *************************************************/ (void) new TDEAction(i18n("Change Grouping"), CTRL + Key_G, TQT_TQOBJECT(this), TQT_SLOT(slotGroupLabelActivated()), actionCollection(), "change_entry_grouping_accel"); m_entryGrouping = new TDESelectAction(i18n("&Group Selection"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotChangeGrouping()), actionCollection(), "change_entry_grouping"); m_entryGrouping->setToolTip(i18n("Change the grouping of the collection")); (void) new TDEAction(i18n("Filter"), CTRL + Key_F, TQT_TQOBJECT(this), TQT_SLOT(slotFilterLabelActivated()), actionCollection(), "quick_filter_accel"); (void) new TDEAction(i18n("Clear Filter"), TQString::fromLatin1("locationbar_erase"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotClearFilter()), actionCollection(), "quick_filter_clear"); m_quickFilter = new GUI::LineEdit(); m_quickFilter->setHint(i18n("Filter here...")); // same text as tdepim and amarok // about 10 characters wide m_quickFilter->setFixedWidth(m_quickFilter->fontMetrics().maxWidth()*10); // want to update every time the filter text changes connect(m_quickFilter, TQT_SIGNAL(textChanged(const TQString&)), TQT_TQOBJECT(this), TQT_SLOT(slotQueueFilter())); m_quickFilter->installEventFilter(this); // intercept keyEvents KWidgetAction* wAction = new KWidgetAction(m_quickFilter, i18n("Filter"), 0, 0, 0, actionCollection(), "quick_filter"); wAction->setToolTip(i18n("Filter the collection")); wAction->setShortcutConfigurable(false); wAction->setAutoSized(true); // show tool tips in status bar actionCollection()->setHighlightingEnabled(true); connect(actionCollection(), TQT_SIGNAL(actionStatusText(const TQString &)), TQT_SLOT(slotStatusMsg(const TQString &))); connect(actionCollection(), TQT_SIGNAL(clearStatusText()), TQT_SLOT(slotClearStatus())); #ifdef UIFILE kdWarning() << "MainWindow::initActions() - change createGUI() call!" << endl; createGUI(UIFILE, false); #else createGUI(TQString(), false); #endif } void MainWindow::initDocument() { MARK; Data::Document* doc = Data::Document::self(); TDEConfigGroup config(TDEGlobal::config(), "General Options"); doc->setLoadAllImages(config.readBoolEntry("Load All Images", false)); // allow status messages from the document connect(doc, TQT_SIGNAL(signalStatusMsg(const TQString&)), TQT_SLOT(slotStatusMsg(const TQString&))); // do stuff that changes when the doc is modified connect(doc, TQT_SIGNAL(signalModified(bool)), TQT_SLOT(slotEnableModifiedActions(bool))); connect(Kernel::self()->commandHistory(), TQT_SIGNAL(commandExecuted()), doc, TQT_SLOT(slotSetModified())); connect(Kernel::self()->commandHistory(), TQT_SIGNAL(documentRestored()), doc, TQT_SLOT(slotDocumentRestored())); } void MainWindow::initView() { MARK; m_split = new TQSplitter(Qt::Horizontal, this); setCentralWidget(m_split); m_viewTabs = new GUI::TabControl(m_split); m_viewTabs->setTabBarHidden(true); m_groupView = new GroupView(m_viewTabs, "groupview"); Controller::self()->addObserver(m_groupView); m_viewTabs->addTab(m_groupView, SmallIcon(TQString::fromLatin1("folder")), i18n("Groups")); TQWhatsThis::add(m_groupView, i18n("The Group View sorts the entries into groupings " "based on a selected field.")); m_rightSplit = new TQSplitter(Qt::Vertical, m_split); m_detailedView = new DetailedListView(m_rightSplit, "detailedlistview"); Controller::self()->addObserver(m_detailedView); TQWhatsThis::add(m_detailedView, i18n("The Column View shows the value of multiple fields " "for each entry.")); connect(Data::Document::self(), TQT_SIGNAL(signalCollectionImagesLoaded(Tellico::Data::CollPtr)), m_detailedView, TQT_SLOT(slotRefreshImages())); m_viewStack = new ViewStack(m_rightSplit, "viewstack"); Controller::self()->addObserver(m_viewStack->iconView()); connect(m_viewStack->entryView(), TQT_SIGNAL(signalAction(const KURL&)), TQT_SLOT(slotURLAction(const KURL&))); setMinimumWidth(MAIN_WINDOW_MIN_WIDTH); } void MainWindow::initConnections() { // have to toggle the menu item if the dialog gets closed connect(m_editDialog, TQT_SIGNAL(finished()), TQT_TQOBJECT(this), TQT_SLOT(slotEditDialogFinished())); // let the group view call filters, too connect(m_groupView, TQT_SIGNAL(signalUpdateFilter(Tellico::FilterPtr)), Controller::self(), TQT_SLOT(slotUpdateFilter(Tellico::FilterPtr))); } void MainWindow::initFileOpen(bool nofile_) { MARK; slotInit(); // check to see if most recent file should be opened bool happyStart = false; if(!nofile_ && Config::reopenLastFile()) { // Config::lastOpenFile() is the full URL, protocol included KURL lastFile(Config::lastOpenFile()); // empty string is actually ok, it gets handled if(!lastFile.isEmpty() && lastFile.isValid()) { slotFileOpen(lastFile); happyStart = true; } } if(!happyStart) { // the document is created with an initial book collection, continue with that Controller::self()->slotCollectionAdded(Data::Document::self()->collection()); m_fileSave->setEnabled(false); slotEnableOpenedActions(); slotEnableModifiedActions(false); slotEntryCount(); const int type = Kernel::self()->collectionType(); TQString welcomeFile = locate("appdata", TQString::fromLatin1("welcome.html")); TQString text = FileHandler::readTextFile(welcomeFile); text.replace(TQString::fromLatin1("$FGCOLOR$"), Config::templateTextColor(type).name()); text.replace(TQString::fromLatin1("$BGCOLOR$"), Config::templateBaseColor(type).name()); text.replace(TQString::fromLatin1("$COLOR1$"), Config::templateHighlightedTextColor(type).name()); text.replace(TQString::fromLatin1("$COLOR2$"), Config::templateHighlightedBaseColor(type).name()); text.replace(TQString::fromLatin1("$IMGDIR$"), TQFile::encodeName(ImageFactory::tempDir())); text.replace(TQString::fromLatin1("$BANNER$"), i18n("Welcome to the Tellico Collection Manager")); text.replace(TQString::fromLatin1("$WELCOMETEXT$"), i18n("

Tellico is a tool for managing collections of books, " "videos, music, and whatever else you want to catalog.

" "

New entries can be added to your collection by " "entering data manually or by " "downloading data from " "various Internet sources.

")); m_viewStack->entryView()->showText(text); } m_initialized = true; } // These are general options. // The options that can be changed in the "Configuration..." dialog // are taken care of by the ConfigDialog object. void MainWindow::saveOptions() { // myDebug() << "MainWindow::saveOptions()" << endl; saveMainWindowSettings(TDEGlobal::config(), TQString::fromLatin1("Main Window Options")); Config::setShowGroupWidget(m_toggleGroupWidget->isChecked()); Config::setShowEditWidget(m_toggleEntryEditor->isChecked()); Config::setShowEntryView(m_toggleEntryView->isChecked()); m_fileOpenRecent->saveEntries(TDEGlobal::config(), TQString::fromLatin1("Recent Files")); if(!isNewDocument()) { Config::setLastOpenFile(Data::Document::self()->URL().url()); } if(m_groupView->isShown()) { Config::setMainSplitterSizes(m_split->sizes()); } if(m_viewStack->isShown()) { // badly named option, but no need to change Config::setSecondarySplitterSizes(m_rightSplit->sizes()); } Config::setGroupViewSortColumn(m_groupView->sortStyle()); // ok to use SortColumn key, save semantics Config::setGroupViewSortAscending(m_groupView->ascendingSort()); if(m_loanView) { Config::setLoanViewSortColumn(m_loanView->sortStyle()); // ok to use SortColumn key, save semantics Config::setLoanViewSortAscending(m_loanView->ascendingSort()); } if(m_filterView) { Config::setFilterViewSortColumn(m_filterView->sortStyle()); // ok to use SortColumn key, save semantics Config::setFilterViewSortAscending(m_filterView->ascendingSort()); } // this is used in the EntryEditDialog constructor, too m_editDialog->saveDialogSize(TQString::fromLatin1("Edit Dialog Options")); saveCollectionOptions(Data::Document::self()->collection()); Config::writeConfig(); } void MainWindow::readCollectionOptions(Data::CollPtr coll_) { TDEConfigGroup group(TDEGlobal::config(), TQString::fromLatin1("Options - %1").arg(coll_->typeName())); TQString defaultGroup = coll_->defaultGroupField(); TQString entryGroup; if(coll_->type() != Data::Collection::Base) { entryGroup = group.readEntry("Group By", defaultGroup); } else { KURL url = Kernel::self()->URL(); for(uint i = 0; i < Config::maxCustomURLSettings(); ++i) { KURL u = group.readEntry(TQString::fromLatin1("URL_%1").arg(i)); if(url == u) { entryGroup = group.readEntry(TQString::fromLatin1("Group By_%1").arg(i), defaultGroup); break; } } // fall back to old setting if(entryGroup.isEmpty()) { entryGroup = group.readEntry("Group By", defaultGroup); } } if(entryGroup.isEmpty() || !coll_->entryGroups().contains(entryGroup)) { entryGroup = defaultGroup; } m_groupView->setGroupField(entryGroup); TQString entryXSLTFile = Config::templateName(coll_->type()); if(entryXSLTFile.isEmpty()) { entryXSLTFile = TQString::fromLatin1("Fancy"); // should never happen, but just in case } m_viewStack->entryView()->setXSLTFile(entryXSLTFile + TQString::fromLatin1(".xsl")); // make sure the right combo element is selected slotUpdateCollectionToolBar(coll_); } void MainWindow::saveCollectionOptions(Data::CollPtr coll_) { // don't save initial collection options, or empty collections if(!coll_ || coll_->entryCount() == 0 || isNewDocument()) { return; } int configIndex = -1; TDEConfigGroup config(TDEGlobal::config(), TQString::fromLatin1("Options - %1").arg(coll_->typeName())); TQString groupName; if(m_entryGrouping->currentItem() > -1 && static_cast(coll_->entryGroups().count()) > m_entryGrouping->currentItem()) { groupName = Kernel::self()->fieldNameByTitle(m_entryGrouping->currentText()); if(coll_->type() != Data::Collection::Base) { config.writeEntry("Group By", groupName); } } if(coll_->type() == Data::Collection::Base) { // all of this is to have custom settings on a per file basis KURL url = Kernel::self()->URL(); TQValueList urls = TQValueList() << url; TQStringList groupBys = TQStringList() << groupName; for(uint i = 0; i < Config::maxCustomURLSettings(); ++i) { KURL u = config.readEntry(TQString::fromLatin1("URL_%1").arg(i)); TQString g = config.readEntry(TQString::fromLatin1("Group By_%1").arg(i)); if(!u.isEmpty() && url != u) { urls.append(u); groupBys.append(g); } else if(!u.isEmpty()) { configIndex = i; } } size_t limit = TQMIN(urls.count(), Config::maxCustomURLSettings()); for(uint i = 0; i < limit; ++i) { config.writeEntry(TQString::fromLatin1("URL_%1").arg(i), urls[i].url()); config.writeEntry(TQString::fromLatin1("Group By_%1").arg(i), groupBys[i]); } } m_detailedView->saveConfig(coll_, configIndex); } void MainWindow::readOptions() { // myDebug() << "MainWindow::readOptions()" << endl; applyMainWindowSettings(TDEGlobal::config(), TQString::fromLatin1("Main Window Options")); TQValueList splitList = Config::mainSplitterSizes(); if(!splitList.empty()) { m_split->setSizes(splitList); } splitList = Config::secondarySplitterSizes(); if(!splitList.empty()) { m_rightSplit->setSizes(splitList); } m_viewStack->iconView()->setMaxAllowedIconWidth(Config::maxIconSize()); connect(toolBar("collectionToolBar"), TQT_SIGNAL(modechange()), TQT_SLOT(slotUpdateToolbarIcons())); m_toggleGroupWidget->setChecked(Config::showGroupWidget()); slotToggleGroupWidget(); m_toggleEntryView->setChecked(Config::showEntryView()); slotToggleEntryView(); // initialize the recent file list m_fileOpenRecent->loadEntries(TDEGlobal::config(), TQString::fromLatin1("Recent Files")); // sort by count if column = 1 int sortStyle = Config::groupViewSortColumn(); m_groupView->setSortStyle(static_cast(sortStyle)); bool sortAscending = Config::groupViewSortAscending(); m_groupView->setSortOrder(sortAscending ? TQt::Ascending : TQt::Descending); m_detailedView->setPixmapSize(Config::maxPixmapWidth(), Config::maxPixmapHeight()); bool useBraces = Config::useBraces(); if(useBraces) { BibtexHandler::s_quoteStyle = BibtexHandler::BRACES; } else { BibtexHandler::s_quoteStyle = BibtexHandler::QUOTES; } // Don't read any options for the edit dialog here, since it's not yet initialized. // Put them in init() } void MainWindow::saveProperties(TDEConfig* cfg_) { if(!isNewDocument() && !Data::Document::self()->isModified()) { // saving to tempfile not necessary } else { KURL url = Data::Document::self()->URL(); cfg_->writeEntry("filename", url.url()); cfg_->writeEntry("modified", Data::Document::self()->isModified()); TQString tempname = KURL::encode_string(kapp->tempSaveName(url.url())); KURL tempurl; tempurl.setPath(tempname); Data::Document::self()->saveDocument(tempurl); } } void MainWindow::readProperties(TDEConfig* cfg_) { TQString filename = cfg_->readEntry(TQString::fromLatin1("filename")); bool modified = cfg_->readBoolEntry(TQString::fromLatin1("modified"), false); if(modified) { bool canRecover; TQString tempname = kapp->checkRecoverFile(filename, canRecover); if(canRecover) { KURL tempurl; tempurl.setPath(tempname); Data::Document::self()->openDocument(tempurl); Data::Document::self()->slotSetModified(true); updateCaption(true); TQFile::remove(tempname); } } else { if(!filename.isEmpty()) { KURL url; url.setPath(filename); Data::Document::self()->openDocument(url); updateCaption(false); } } } bool MainWindow::queryClose() { // in case we're still loading the images, cancel that Data::Document::self()->cancelImageWriting(); return m_editDialog->queryModified() && Data::Document::self()->saveModified(); } bool MainWindow::queryExit() { FileHandler::clean(); ImageFactory::clean(true); saveOptions(); return true; } void MainWindow::slotFileNew(int type_) { slotStatusMsg(i18n("Creating new document...")); // close the fields dialog slotHideCollectionFieldsDialog(); if(m_editDialog->queryModified() && Data::Document::self()->saveModified()) { // remove filter and loan tabs, they'll get re-added if needed if(m_filterView) { m_viewTabs->removePage(m_filterView); Controller::self()->removeObserver(m_filterView); delete m_filterView; m_filterView = 0; } if(m_loanView) { m_viewTabs->removePage(m_loanView); Controller::self()->removeObserver(m_loanView); delete m_loanView; m_loanView = 0; } m_viewTabs->setTabBarHidden(true); Data::Document::self()->newDocument(type_); m_fileOpenRecent->setCurrentItem(-1); slotEnableOpenedActions(); slotEnableModifiedActions(false); m_newDocument = true; ImageFactory::clean(false); } StatusBar::self()->clearStatus(); } void MainWindow::slotFileOpen() { slotStatusMsg(i18n("Opening file...")); if(m_editDialog->queryModified() && Data::Document::self()->saveModified()) { TQString filter = i18n("*.tc *.bc|Tellico Files (*.tc)"); filter += TQString::fromLatin1("\n"); filter += i18n("*.xml|XML Files (*.xml)"); filter += TQString::fromLatin1("\n"); filter += i18n("*|All Files"); // keyword 'open' KURL url = KFileDialog::getOpenURL(TQString::fromLatin1(":open"), filter, this, i18n("Open File")); if(!url.isEmpty() && url.isValid()) { slotFileOpen(url); } } StatusBar::self()->clearStatus(); } void MainWindow::slotFileOpen(const KURL& url_) { slotStatusMsg(i18n("Opening file...")); // close the fields dialog slotHideCollectionFieldsDialog(); // there seems to be a race condition at start between slotInit() and initFileOpen() // which means the edit dialog might not have been created yet if((!m_editDialog || m_editDialog->queryModified()) && Data::Document::self()->saveModified()) { if(openURL(url_)) { m_fileOpenRecent->addURL(url_); m_fileOpenRecent->setCurrentItem(-1); } } StatusBar::self()->clearStatus(); } void MainWindow::slotFileOpenRecent(const KURL& url_) { slotStatusMsg(i18n("Opening file...")); // close the fields dialog slotHideCollectionFieldsDialog(); if(m_editDialog->queryModified() && Data::Document::self()->saveModified()) { if(!openURL(url_)) { m_fileOpenRecent->removeURL(url_); m_fileOpenRecent->setCurrentItem(-1); } } else { // the TDEAction shouldn't be checked now m_fileOpenRecent->setCurrentItem(-1); } StatusBar::self()->clearStatus(); } void MainWindow::openFile(const TQString& file_) { KURL url = KURL::fromPathOrURL(file_); if(!url.isEmpty() && url.isValid()) { slotFileOpen(url); } } bool MainWindow::openURL(const KURL& url_) { // myDebug() << "MainWindow::openURL() - " << url_.prettyURL() << endl; // try to open document GUI::CursorSaver cs(TQt::waitCursor); bool success = Data::Document::self()->openDocument(url_); if(success) { m_quickFilter->clear(); slotEnableOpenedActions(); m_newDocument = false; slotEnableModifiedActions(Data::Document::self()->isModified()); // doc might add some stuff } else if(!m_initialized) { // special case on startup when openURL() is called with a command line argument // and that URL can't be opened. The window still needs to be initialized // the doc object is created with an initial book collection, continue with that Controller::self()->slotCollectionAdded(Data::Document::self()->collection()); m_fileSave->setEnabled(false); slotEnableOpenedActions(); slotEnableModifiedActions(false); slotEntryCount(); } // slotFileOpen(URL) gets called when opening files on the command line // so go ahead and make sure m_initialized is set. m_initialized = true; // remove filter and loan tabs, they'll get re-added if needed if(m_filterView && m_filterView->childCount() == 0) { m_viewTabs->removePage(m_filterView); Controller::self()->removeObserver(m_filterView); delete m_filterView; m_filterView = 0; } if(m_loanView && m_loanView->childCount() == 0) { m_viewTabs->removePage(m_loanView); Controller::self()->removeObserver(m_loanView); delete m_loanView; m_loanView = 0; } Controller::self()->hideTabs(); // does conditional check return success; } void MainWindow::slotFileSave() { fileSave(); } bool MainWindow::fileSave() { if(!m_editDialog->queryModified()) { return false; } slotStatusMsg(i18n("Saving file...")); bool ret = true; if(isNewDocument()) { ret = fileSaveAs(); } else { // special check: if there are more than 200 images AND the "Write Images In File" config key // is not set, then warn user that performance may suffer, and write result if(Config::imageLocation() == Config::ImagesInFile && Config::askWriteImagesInFile() && Data::Document::self()->imageCount() > MAX_IMAGES_WARN_PERFORMANCE) { TQString msg = i18n("

You are saving a file with many images, which causes Tellico to " "slow down significantly. Do you want to save the images separately in " "Tellico's data directory to improve performance?

Your choice can " "always be changed in the configuration dialog.

"); KGuiItem yes(i18n("Save Images Separately")); KGuiItem no(i18n("Save Images in File")); int res = KMessageBox::warningYesNo(this, msg, TQString() /* caption */, yes, no); if(res == KMessageBox::No) { Config::setImageLocation(Config::ImagesInAppDir); } Config::setAskWriteImagesInFile(false); } GUI::CursorSaver cs(TQt::waitCursor); if(Data::Document::self()->saveDocument(Data::Document::self()->URL())) { m_newDocument = false; updateCaption(false); m_fileSave->setEnabled(false); m_detailedView->resetEntryStatus(); } else { ret = false; } } StatusBar::self()->clearStatus(); return ret; } void MainWindow::slotFileSaveAs() { fileSaveAs(); } bool MainWindow::fileSaveAs() { if(!m_editDialog->queryModified()) { return false; } slotStatusMsg(i18n("Saving file with a new filename...")); TQString filter = i18n("*.tc *.bc|Tellico Files (*.tc)"); filter += TQChar('\n'); filter += i18n("*|All Files"); // keyword 'open' KFileDialog dlg(TQString::fromLatin1(":open"), filter, this, "filedialog", true); dlg.setCaption(i18n("Save As")); dlg.setOperationMode(KFileDialog::Saving); int result = dlg.exec(); if(result == TQDialog::Rejected) { StatusBar::self()->clearStatus(); return false; } bool ret = true; KURL url = dlg.selectedURL(); if(!url.isEmpty() && url.isValid()) { GUI::CursorSaver cs(TQt::waitCursor); if(Data::Document::self()->saveDocument(url)) { TDERecentDocument::add(url); m_fileOpenRecent->addURL(url); updateCaption(false); m_newDocument = false; m_fileSave->setEnabled(false); m_detailedView->resetEntryStatus(); } else { ret = false; } } StatusBar::self()->clearStatus(); return ret; } void MainWindow::slotFilePrint() { slotStatusMsg(i18n("Printing...")); bool printGrouped = Config::printGrouped(); bool printHeaders = Config::printFieldHeaders(); int imageWidth = Config::maxImageWidth(); int imageHeight = Config::maxImageHeight(); // If the collection is being filtered, warn the user if(m_detailedView->filter() != 0) { TQString str = i18n("The collection is currently being filtered to show a limited subset of " "the entries. Only the visible entries will be printed. Continue?"); int ret = KMessageBox::warningContinueCancel(this, str, TQString(), KStdGuiItem::print(), TQString::fromLatin1("WarnPrintVisible")); if(ret == KMessageBox::Cancel) { StatusBar::self()->clearStatus(); return; } } GUI::CursorSaver cs(TQt::waitCursor); Export::HTMLExporter exporter(Data::Document::self()->collection()); // only print visible entries exporter.setEntries(m_detailedView->visibleEntries()); exporter.setXSLTFile(TQString::fromLatin1("tellico-printing.xsl")); exporter.setPrintHeaders(printHeaders); exporter.setPrintGrouped(printGrouped); exporter.setGroupBy(Controller::self()->expandedGroupBy()); if(!printGrouped) { // the sort titles are only used if the entries are not grouped exporter.setSortTitles(Controller::self()->sortTitles()); } exporter.setColumns(m_detailedView->visibleColumns()); exporter.setMaxImageSize(imageWidth, imageHeight); slotStatusMsg(i18n("Processing document...")); if(Config::printFormatted()) { exporter.setOptions(Export::ExportUTF8 | Export::ExportFormatted); } else { exporter.setOptions(Export::ExportUTF8); } TQString html = exporter.text(); if(html.isEmpty()) { XSLTError(); StatusBar::self()->clearStatus(); return; } // don't have busy cursor when showing the print dialog cs.restore(); // myDebug() << html << endl; slotStatusMsg(i18n("Printing...")); doPrint(html); StatusBar::self()->clearStatus(); } void MainWindow::slotFileQuit() { slotStatusMsg(i18n("Exiting...")); // this gets called in queryExit() anyway //saveOptions(); close(); StatusBar::self()->clearStatus(); } void MainWindow::slotEditCut() { activateEditSlot(TQT_SLOT(cut())); } void MainWindow::slotEditCopy() { activateEditSlot(TQT_SLOT(copy())); } void MainWindow::slotEditPaste() { activateEditSlot(TQT_SLOT(paste())); } void MainWindow::activateEditSlot(const char* slot_) { // the edit widget is the only one that copies, cuts, and pastes TQWidget* w; if(m_editDialog->isVisible()) { w = m_editDialog->focusWidget(); } else { w = kapp->focusWidget(); } if(w && w->isVisible()) { TQMetaObject* meta = w->metaObject(); int idx = meta->findSlot(slot_ + 1, true); if(idx > -1) { w->tqt_invoke(idx, 0); } } } void MainWindow::slotEditSelectAll() { m_detailedView->selectAllVisible(); } void MainWindow::slotEditDeselect() { Controller::self()->slotUpdateSelection(0, Data::EntryVec()); } void MainWindow::slotConfigToolbar() { saveMainWindowSettings(TDEGlobal::config(), TQString::fromLatin1("Main Window Options")); #ifdef UIFILE KEditToolbar dlg(actionCollection(), UIFILE); #else KEditToolbar dlg(actionCollection()); #endif connect(&dlg, TQT_SIGNAL(newToolbarConfig()), TQT_TQOBJECT(this), TQT_SLOT(slotNewToolbarConfig())); dlg.exec(); } void MainWindow::slotNewToolbarConfig() { applyMainWindowSettings(TDEGlobal::config(), TQString::fromLatin1("Main Window Options")); #ifdef UIFILE createGUI(UIFILE, false); #else createGUI(TQString(), false); #endif } void MainWindow::slotConfigKeys() { KKeyDialog::configure(actionCollection()); } void MainWindow::slotToggleGroupWidget() { if(m_toggleGroupWidget->isChecked()) { m_viewTabs->show(); } else { m_viewTabs->hide(); } } void MainWindow::slotToggleEntryEditor() { if(m_toggleEntryEditor->isChecked()) { m_editDialog->show(); } else { m_editDialog->hide(); } } void MainWindow::slotToggleEntryView() { if(m_toggleEntryView->isChecked()) { m_viewStack->show(); } else { m_viewStack->hide(); } } void MainWindow::slotShowConfigDialog() { if(!m_configDlg) { m_configDlg = new ConfigDialog(this); m_configDlg->show(); m_configDlg->readConfiguration(); connect(m_configDlg, TQT_SIGNAL(signalConfigChanged()), TQT_SLOT(slotHandleConfigChange())); connect(m_configDlg, TQT_SIGNAL(finished()), TQT_SLOT(slotHideConfigDialog())); } else { KWin::activateWindow(m_configDlg->winId()); m_configDlg->show(); } } void MainWindow::slotHideConfigDialog() { if(m_configDlg) { m_configDlg->delayedDestruct(); m_configDlg = 0; } } void MainWindow::slotShowTipOfDay(bool force_/*=true*/) { TQString tipfile = locate("appdata", TQString::fromLatin1("tellico.tips")); KTipDialog::showTip(this, tipfile, force_); } void MainWindow::slotStatusMsg(const TQString& text_) { m_statusBar->setStatus(text_); } void MainWindow::slotClearStatus() { StatusBar::self()->clearStatus(); } void MainWindow::slotEntryCount() { Data::CollPtr coll = Data::Document::self()->collection(); if(!coll) { return; } size_t count = coll->entryCount(); TQString text = i18n("Total entries: %1").arg(count); size_t selectCount = Controller::self()->selectedEntries().count(); size_t filterCount = m_detailedView->visibleItems(); // if more than one book is selected, add the number of selected books if(filterCount < count && selectCount > 1) { text += TQChar(' '); text += i18n("(%1 filtered; %2 selected)").arg(filterCount).arg(selectCount); } else if(filterCount < count) { text += TQChar(' '); text += i18n("(%1 filtered)").arg(filterCount); } else if(selectCount > 1) { text += TQChar(' '); text += i18n("(%1 selected)").arg(selectCount); } m_statusBar->setCount(text); } void MainWindow::slotEnableOpenedActions() { slotUpdateToolbarIcons(); // collapse all the groups (depth=1) m_groupView->slotCollapseAll(1); updateCollectionActions(); // close the filter dialog when a new collection is opened slotHideFilterDialog(); slotHideStringMacroDialog(); } void MainWindow::slotEnableModifiedActions(bool modified_ /*= true*/) { updateCaption(modified_); updateCollectionActions(); m_fileSave->setEnabled(modified_); } void MainWindow::slotHandleConfigChange() { const int imageLocation = Config::imageLocation(); const bool autoCapitalize = Config::autoCapitalization(); const bool autoFormat = Config::autoFormat(); TQStringList articles = Config::articleList(); TQStringList nocaps = Config::noCapitalizationList(); TQStringList suffixes = Config::nameSuffixList(); TQStringList prefixes = Config::surnamePrefixList(); m_configDlg->saveConfiguration(); // only modified if there are entries and image location is changed if(imageLocation != Config::imageLocation() && !Data::Document::self()->isEmpty()) { Data::Document::self()->slotSetModified(); } if(autoCapitalize != Config::autoCapitalization() || autoFormat != Config::autoFormat() || articles != Config::articleList() || nocaps != Config::noCapitalizationList() || suffixes != Config::nameSuffixList() || prefixes != Config::surnamePrefixList()) { // invalidate all groups Data::Document::self()->collection()->invalidateGroups(); // refreshing the title causes the group view to refresh Controller::self()->slotRefreshField(Data::Document::self()->collection()->fieldByName(TQString::fromLatin1("title"))); } TQString entryXSLTFile = Config::templateName(Kernel::self()->collectionType()); m_viewStack->entryView()->setXSLTFile(entryXSLTFile + TQString::fromLatin1(".xsl")); } void MainWindow::slotUpdateCollectionToolBar(Data::CollPtr coll_) { // myDebug() << "MainWindow::updateCollectionToolBar()" << endl; if(!coll_) { kdWarning() << "MainWindow::slotUpdateCollectionToolBar() - no collection pointer!" << endl; return; } TQString current = m_groupView->groupBy(); if(current.isEmpty() || !coll_->entryGroups().contains(current)) { current = coll_->defaultGroupField(); } const TQStringList groups = coll_->entryGroups(); if(groups.isEmpty()) { m_entryGrouping->clear(); return; } TQMap groupMap; // use a map so they get sorted for(TQStringList::ConstIterator groupIt = groups.begin(); groupIt != groups.end(); ++groupIt) { // special case for people "pseudo-group" if(*groupIt == Data::Collection::s_peopleGroupName) { groupMap.insert(*groupIt, TQString::fromLatin1("<") + i18n("People") + TQString::fromLatin1(">")); } else { groupMap.insert(*groupIt, coll_->fieldTitleByName(*groupIt)); } } TQStringList names = groupMap.keys(); int index = names.findIndex(current); if(index == -1) { current = names[0]; index = 0; } TQStringList titles = groupMap.values(); m_entryGrouping->setItems(titles); m_entryGrouping->setCurrentItem(index); // in case the current grouping field get modified to be non-grouping... m_groupView->setGroupField(current); // don't call slotChangeGrouping() since it adds an undo item // this isn't really proper, but works so the combo box width gets adjusted const int len = m_entryGrouping->containerCount(); for(int i = 0; i < len; ++i) { TDEToolBar* tb = dynamic_cast(m_entryGrouping->container(i)); if(tb) { KComboBox* cb = tb->getCombo(m_entryGrouping->itemId(i)); if(cb) { // qt caches the combobox size and never recalculates the sizeHint() // the source code recommends calling setFont to invalidate the sizeHint cb->setFont(cb->font()); cb->updateGeometry(); } } } } void MainWindow::slotChangeGrouping() { // myDebug() << "MainWindow::slotChangeGrouping()" << endl; TQString title = m_entryGrouping->currentText(); TQString groupName = Kernel::self()->fieldNameByTitle(title); if(groupName.isEmpty()) { if(title == TQString::fromLatin1("<") + i18n("People") + TQString::fromLatin1(">")) { groupName = Data::Collection::s_peopleGroupName; } else { groupName = Data::Document::self()->collection()->defaultGroupField(); } } m_groupView->setGroupField(groupName); m_viewTabs->showPage(m_groupView); } void MainWindow::slotShowReportDialog() { // myDebug() << "MainWindow::slotShowReport()" << endl; if(!m_reportDlg) { m_reportDlg = new ReportDialog(this); connect(m_reportDlg, TQT_SIGNAL(finished()), TQT_SLOT(slotHideReportDialog())); } else { KWin::activateWindow(m_reportDlg->winId()); } m_reportDlg->show(); } void MainWindow::slotHideReportDialog() { if(m_reportDlg) { m_reportDlg->delayedDestruct(); m_reportDlg = 0; } } void MainWindow::doPrint(const TQString& html_) { TDEHTMLPart w ; w.setJScriptEnabled(false); w.setJavaEnabled(false); w.setMetaRefreshEnabled(false); w.setPluginsEnabled(false); w.begin(Data::Document::self()->URL()); w.write(html_); w.end(); // the problem with doing my own layout is that the text gets truncated, both at the // top and at the bottom. Even adding the overlap parameter, there were problems. // TDEHTMLView takes care of that with a truncatedAt() parameter, but that's hidden in // the tdehtml::render_root class. So for now, just use the TDEHTMLView::print() method. #if 1 w.view()->print(); #else KPrinter* printer = new KPrinter(TQPrinter::PrinterResolution); if(printer->setup(this, i18n("Print %1").arg(Data::Document::self()->URL().prettyURL()))) { printer->setFullPage(false); printer->setCreator(TQString::fromLatin1("Tellico")); printer->setDocName(Data::Document::self()->URL().prettyURL()); TQPainter *p = new TQPainter; p->begin(printer); // mostly taken from TDEHTMLView::print() TQString headerLeft = TDEGlobal::locale()->formatDate(TQDate::currentDate(), false); TQString headerRight = Data::Document::self()->URL().prettyURL(); TQString footerMid; TQFont headerFont(TQString::fromLatin1("helvetica"), 8); p->setFont(headerFont); const int lspace = p->fontMetrics().lineSpacing(); const int headerHeight = (lspace * 3) / 2; TQPaintDeviceMetrics metrics(printer); const int pageHeight = metrics.height() - 2*headerHeight; const int pageWidth = metrics.width(); // myDebug() << "MainWindow::doPrint() - pageHeight = " << pageHeight << "" // "; contentsHeight = " << w->view()->contentsHeight() << endl; int top = 0; int page = 1; bool more = true; while(more) { p->setPen(TQt::black); p->setFont(headerFont); footerMid = i18n("Page %1").arg(page); p->drawText(0, 0, pageWidth, lspace, TQt::AlignLeft, headerLeft); p->drawText(0, 0, pageWidth, lspace, TQt::AlignRight, headerRight); p->drawText(0, pageHeight+headerHeight, pageWidth, lspace, TQt::AlignHCenter, footerMid); w->paint(p, TQRect(0, -top + 2*headerHeight, pageWidth, pageHeight+top), top, &more); top += pageHeight - PRINTED_PAGE_OVERLAP; if(more) { printer->newPage(); page++; } // p->resetXForm(); } // stop painting, this will automatically send the print data to the printer p->end(); delete p; } delete printer; #endif } void MainWindow::XSLTError() { TQString str = i18n("Tellico encountered an error in XSLT processing.") + TQChar('\n'); str += i18n("Please check your installation."); Kernel::self()->sorry(str); } void MainWindow::slotShowFilterDialog() { if(!m_filterDlg) { m_filterDlg = new FilterDialog(FilterDialog::CreateFilter, this); // allow saving m_filterDlg->setFilter(m_detailedView->filter()); m_quickFilter->setEnabled(false); connect(m_filterDlg, TQT_SIGNAL(signalCollectionModified()), Data::Document::self(), TQT_SLOT(slotSetModified())); connect(m_filterDlg, TQT_SIGNAL(signalUpdateFilter(Tellico::FilterPtr)), m_quickFilter, TQT_SLOT(clear())); connect(m_filterDlg, TQT_SIGNAL(signalUpdateFilter(Tellico::FilterPtr)), Controller::self(), TQT_SLOT(slotUpdateFilter(Tellico::FilterPtr))); connect(m_filterDlg, TQT_SIGNAL(finished()), TQT_SLOT(slotHideFilterDialog())); } else { KWin::activateWindow(m_filterDlg->winId()); } m_filterDlg->show(); } void MainWindow::slotHideFilterDialog() { // m_quickFilter->blockSignals(false); m_quickFilter->setEnabled(true); if(m_filterDlg) { m_filterDlg->delayedDestruct(); m_filterDlg = 0; } } void MainWindow::slotQueueFilter() { m_queuedFilters++; TQTimer::singleShot(200, TQT_TQOBJECT(this), TQT_SLOT(slotUpdateFilter())); } void MainWindow::slotUpdateFilter() { m_queuedFilters--; if(m_queuedFilters > 0) { return; } setFilter(m_quickFilter->text()); } void MainWindow::setFilter(const TQString& text_) { TQString text = text_.stripWhiteSpace(); Filter::Ptr filter = 0; if(!text.isEmpty()) { filter = new Filter(Filter::MatchAll); TQString fieldName = TQString(); // if the text contains '=' assume it's a field name or title if(text.find('=') > -1) { fieldName = text.section('=', 0, 0).stripWhiteSpace(); text = text.section('=', 1).stripWhiteSpace(); // check that the field name might be a title if(!Data::Document::self()->collection()->hasField(fieldName)) { fieldName = Data::Document::self()->collection()->fieldNameByTitle(fieldName); } } // if the text contains any non-word characters, assume it's a regexp // but \W in qt is letter, number, or '_', I want to be a bit less strict TQRegExp rx(TQString::fromLatin1("[^\\w\\s-']")); if(text.find(rx) == -1) { // split by whitespace, and add rules for each word TQStringList tokens = TQStringList::split(TQRegExp(TQString::fromLatin1("\\s")), text); for(TQStringList::Iterator it = tokens.begin(); it != tokens.end(); ++it) { // an empty field string means check every field filter->append(new FilterRule(fieldName, *it, FilterRule::FuncContains)); } } else { // if it isn't valid, hold off on applying the filter TQRegExp tx(text); if(!tx.isValid()) { text = TQRegExp::escape(text); tx.setPattern(text); } if(!tx.isValid()) { myDebug() << "MainWindow::slotUpdateFilter() - invalid regexp: " << text << endl; return; } filter->append(new FilterRule(fieldName, text, FilterRule::FuncRegExp)); } // also want to update the line edit in case the filter was set by DCOP if(m_quickFilter->text().isEmpty() && m_quickFilter->text() != text_) { m_quickFilter->setText(text_); } } // only update filter if one exists or did exist if(filter || m_detailedView->filter()) { Controller::self()->slotUpdateFilter(filter); } } void MainWindow::slotShowCollectionFieldsDialog() { if(!m_collFieldsDlg) { m_collFieldsDlg = new CollectionFieldsDialog(Data::Document::self()->collection(), this); connect(m_collFieldsDlg, TQT_SIGNAL(finished()), TQT_SLOT(slotHideCollectionFieldsDialog())); } else { KWin::activateWindow(m_collFieldsDlg->winId()); } m_collFieldsDlg->show(); } void MainWindow::slotHideCollectionFieldsDialog() { if(m_collFieldsDlg) { m_collFieldsDlg->delayedDestruct(); m_collFieldsDlg = 0; } } void MainWindow::slotFileImport(int format_) { slotStatusMsg(i18n("Importing data...")); m_quickFilter->clear(); Import::Format format = static_cast(format_); bool checkURL = true; KURL url; switch(ImportDialog::importTarget(format)) { case Import::File: url = KFileDialog::getOpenURL(ImportDialog::startDir(format), ImportDialog::fileFilter(format), this, i18n("Import File")); break; case Import::Dir: // TODO: allow remote audiofile importing url.setPath(KFileDialog::getExistingDirectory(ImportDialog::startDir(format), this, i18n("Import Directory"))); break; case Import::None: default: checkURL = false; break; } if(checkURL) { bool ok = !url.isEmpty() && url.isValid() && TDEIO::NetAccess::exists(url, true, this); if(!ok) { StatusBar::self()->clearStatus(); return; } } importFile(format, url); StatusBar::self()->clearStatus(); } void MainWindow::slotFileExport(int format_) { slotStatusMsg(i18n("Exporting data...")); Export::Format format = static_cast(format_); ExportDialog dlg(format, Data::Document::self()->collection(), this, "exportdialog"); if(dlg.exec() == TQDialog::Rejected) { StatusBar::self()->clearStatus(); return; } switch(ExportDialog::exportTarget(format)) { case Export::None: dlg.exportURL(); break; case Export::Dir: myDebug() << "MainWindow::slotFileExport() - ExportDir not implemented!" << endl; break; case Export::File: { KFileDialog fileDlg(TQString::fromLatin1(":export"), dlg.fileFilter(), this, "filedialog", true); fileDlg.setCaption(i18n("Export As")); fileDlg.setOperationMode(KFileDialog::Saving); if(fileDlg.exec() == TQDialog::Rejected) { StatusBar::self()->clearStatus(); return; } KURL url = fileDlg.selectedURL(); if(!url.isEmpty() && url.isValid()) { GUI::CursorSaver cs(TQt::waitCursor); dlg.exportURL(url); } } break; } StatusBar::self()->clearStatus(); } void MainWindow::slotShowStringMacroDialog() { if(Data::Document::self()->collection()->type() != Data::Collection::Bibtex) { return; } if(!m_stringMacroDlg) { const Data::BibtexCollection* c = static_cast(Data::Document::self()->collection().data()); m_stringMacroDlg = new StringMapDialog(c->macroList(), this, "StringMacroDialog", false); m_stringMacroDlg->setCaption(i18n("String Macros")); m_stringMacroDlg->setLabels(i18n("Macro"), i18n("String")); connect(m_stringMacroDlg, TQT_SIGNAL(finished()), TQT_SLOT(slotHideStringMacroDialog())); connect(m_stringMacroDlg, TQT_SIGNAL(okClicked()), TQT_SLOT(slotStringMacroDialogOk())); } else { KWin::activateWindow(m_stringMacroDlg->winId()); } m_stringMacroDlg->show(); } void MainWindow::slotHideStringMacroDialog() { if(m_stringMacroDlg) { m_stringMacroDlg->delayedDestruct(); m_stringMacroDlg = 0; } } void MainWindow::slotStringMacroDialogOk() { // no point in checking if collection is bibtex, as dialog would never have been created if(m_stringMacroDlg) { static_cast(Data::Document::self()->collection().data())->setMacroList(m_stringMacroDlg->stringMap()); Data::Document::self()->slotSetModified(true); } } void MainWindow::slotNewEntry() { m_toggleEntryEditor->setChecked(true); slotToggleEntryEditor(); m_editDialog->slotHandleNew(); } void MainWindow::slotEditDialogFinished() { m_toggleEntryEditor->setChecked(false); } void MainWindow::slotShowEntryEditor() { m_toggleEntryEditor->setChecked(true); m_editDialog->show(); KWin::activateWindow(m_editDialog->winId()); } void MainWindow::slotConvertToBibliography() { // only book collections can be converted to bibtex Data::CollPtr coll = Data::Document::self()->collection(); if(!coll || coll->type() != Data::Collection::Book) { return; } GUI::CursorSaver cs; Data::CollPtr newColl = Data::BibtexCollection::convertBookCollection(coll); if(newColl) { m_newDocument = true; Kernel::self()->replaceCollection(newColl); m_fileOpenRecent->setCurrentItem(-1); slotUpdateToolbarIcons(); updateCollectionActions(); } else { kdWarning() << "MainWindow::slotConvertToBibliography() - ERROR: no bibliography created!" << endl; } } void MainWindow::slotCiteEntry(int action_) { StatusBar::self()->setStatus(i18n("Creating citations...")); Cite::ActionManager::self()->cite(static_cast(action_), Controller::self()->selectedEntries()); StatusBar::self()->clearStatus(); } void MainWindow::slotShowFetchDialog() { if(!m_fetchDlg) { m_fetchDlg = new FetchDialog(this); connect(m_fetchDlg, TQT_SIGNAL(finished()), TQT_SLOT(slotHideFetchDialog())); connect(Controller::self(), TQT_SIGNAL(collectionAdded(int)), m_fetchDlg, TQT_SLOT(slotResetCollection())); } else { KWin::activateWindow(m_fetchDlg->winId()); } m_fetchDlg->show(); } void MainWindow::slotHideFetchDialog() { if(m_fetchDlg) { m_fetchDlg->delayedDestruct(); m_fetchDlg = 0; } } bool MainWindow::importFile(Import::Format format_, const KURL& url_, Import::Action action_) { // try to open document GUI::CursorSaver cs(TQt::waitCursor); bool failed = false; Data::CollPtr coll; if(!url_.isEmpty() && url_.isValid() && TDEIO::NetAccess::exists(url_, true, this)) { coll = ImportDialog::importURL(format_, url_); } else { Kernel::self()->sorry(i18n(errorLoad).arg(url_.fileName())); failed = true; } if(!coll && !m_initialized) { // special case on startup when openURL() is called with a command line argument // and that URL can't be opened. The window still needs to be initialized // the doc object is created with an initial book collection, continue with that Controller::self()->slotCollectionAdded(Data::Document::self()->collection()); m_fileSave->setEnabled(false); slotEnableOpenedActions(); slotEnableModifiedActions(false); slotEntryCount(); m_fileOpenRecent->setCurrentItem(-1); m_initialized = true; failed = true; } else if(coll) { // this is rather dumb, but I'm too lazy to find the bug // if the document isn't initialized, then Tellico crashes // since Document::replaceCollection() ends up calling lots of stuff that isn't initialized if(!m_initialized) { Controller::self()->slotCollectionAdded(Data::Document::self()->collection()); m_initialized = true; } failed = !importCollection(coll, action_); } StatusBar::self()->clearStatus(); return !failed; // return true means success } bool MainWindow::exportCollection(Export::Format format_, const KURL& url_) { if(!url_.isValid()) { myDebug() << "MainWindow::exportCollection() - invalid URL: " << url_.url() << endl; return false; } GUI::CursorSaver cs; const Data::CollPtr c = Data::Document::self()->collection(); if(!c) { return false; } // only bibliographies can export to bibtex or bibtexml bool isBibtex = (c->type() == Data::Collection::Bibtex); if(!isBibtex && (format_ == Export::Bibtex || format_ == Export::Bibtexml)) { return false; } // only books and bibliographies can export to alexandria bool isBook = (c->type() == Data::Collection::Book); if(!isBibtex && !isBook && format_ == Export::Alexandria) { return false; } bool success = ExportDialog::exportCollection(format_, url_); return success; } bool MainWindow::showEntry(long id) { Data::EntryPtr entry = Data::Document::self()->collection()->entryById(id); if(entry) { m_viewStack->showEntry(entry); } return entry != 0; } void MainWindow::addFilterView() { if(m_filterView) { return; } m_filterView = new FilterView(m_viewTabs, "filterview"); Controller::self()->addObserver(m_filterView); m_viewTabs->insertTab(m_filterView, SmallIcon(TQString::fromLatin1("filter")), i18n("Filters"), 1); TQWhatsThis::add(m_filterView, i18n("The Filter View shows the entries which meet certain " "filter rules.")); int sortStyle = Config::filterViewSortColumn(); m_filterView->setSortStyle(static_cast(sortStyle)); bool sortAscending = Config::filterViewSortAscending(); m_filterView->setSortOrder(sortAscending ? TQt::Ascending : TQt::Descending); } void MainWindow::addLoanView() { if(m_loanView) { return; } m_loanView = new LoanView(m_viewTabs, "loanview"); Controller::self()->addObserver(m_loanView); m_viewTabs->insertTab(m_loanView, SmallIcon(TQString::fromLatin1("kaddressbook")), i18n("Loans"), 2); TQWhatsThis::add(m_loanView, i18n("The Loan View shows a list of all the people who " "have borrowed items from your collection.")); int sortStyle = Config::loanViewSortColumn(); m_loanView->setSortStyle(static_cast(sortStyle)); bool sortAscending = Config::loanViewSortAscending(); m_loanView->setSortOrder(sortAscending ? TQt::Ascending : TQt::Descending); } void MainWindow::updateCaption(bool modified_) { TQString caption; if(Data::Document::self()->collection()) { caption = Data::Document::self()->collection()->title(); } if(!m_newDocument) { if(!caption.isEmpty()) { caption += TQString::fromLatin1(" - "); } KURL u = Data::Document::self()->URL(); if(u.isLocalFile()) { // for new files, the path is set to /Untitled in Data::Document if(u.path() == '/' + i18n("Untitled")) { caption += u.fileName(); } else { caption += u.path(); } } else { caption += u.prettyURL(); } } setCaption(caption, modified_); } void MainWindow::slotUpdateToolbarIcons() { // myDebug() << "MainWindow::slotUpdateToolbarIcons() " << endl; // first change the icon for the menu item m_newEntry->setIconSet(UserIconSet(Kernel::self()->collectionTypeName())); // since the toolbar icon is probably a different size than the menu item icon // superimpose it on the "mime_empty" icon TDEToolBar* tb = toolBar("collectionToolBar"); if(!tb) { return; } for(int i = 0; i < tb->count(); ++i) { if(m_newEntry->isPlugged(tb, tb->idAt(i))) { TQIconSet icons; icons.installIconFactory(new EntryIconFactory(tb->iconSize())); tb->setButtonIconSet(tb->idAt(i), icons); break; } } } void MainWindow::slotGroupLabelActivated() { // need entry grouping combo id TDEToolBar* tb = toolBar("collectionToolBar"); if(!tb) { return; } for(int i = 0; i < tb->count(); ++i) { if(m_entryGrouping->isPlugged(tb, tb->idAt(i))) { KComboBox* combo = tb->getCombo(tb->idAt(i)); if(combo) { combo->popup(); break; } } } } void MainWindow::slotFilterLabelActivated() { m_quickFilter->setFocus(); m_quickFilter->selectAll(); } void MainWindow::slotClearFilter() { m_quickFilter->clear(); slotQueueFilter(); } void MainWindow::slotRenameCollection() { Kernel::self()->renameCollection(); } void MainWindow::updateCollectionActions() { if(!Data::Document::self()->collection()) { return; } stateChanged(TQString::fromLatin1("collection_reset")); Data::Collection::Type type = Data::Document::self()->collection()->type(); switch(type) { case Data::Collection::Book: stateChanged(TQString::fromLatin1("is_book")); break; case Data::Collection::Bibtex: stateChanged(TQString::fromLatin1("is_bibliography")); break; case Data::Collection::Video: stateChanged(TQString::fromLatin1("is_video")); break; default: break; } Controller::self()->updateActions(); // special case when there are no available data sources if(m_fetchActions.isEmpty() && m_updateAll) { m_updateAll->setEnabled(false); } } void MainWindow::updateEntrySources() { TQSignalMapper* mapper = ::tqqt_cast(child("update_mapper")); if(!mapper) { kdWarning() << "MainWindow::updateEntrySources() - no update mapper!" << endl; return; } unplugActionList(TQString::fromLatin1("update_entry_actions")); for(TQPtrListIterator it(m_fetchActions); it.current(); ++it) { it.current()->unplugAll(); mapper->removeMappings(it.current()); } // autoDelete() all actions, which removes them from the actionCollection() m_fetchActions.clear(); Fetch::FetcherVec vec = Fetch::Manager::self()->fetchers(Kernel::self()->collectionType()); for(Fetch::FetcherVec::Iterator it = vec.begin(); it != vec.end(); ++it) { TDEAction* action = new TDEAction(actionCollection()); action->setText(it->source()); action->setToolTip(i18n("Update entry data from %1").arg(it->source())); action->setIconSet(Fetch::Manager::fetcherIcon(it.data())); connect(action, TQT_SIGNAL(activated()), mapper, TQT_SLOT(map())); mapper->setMapping(action, it->source()); m_fetchActions.append(action); } plugActionList(TQString::fromLatin1("update_entry_actions"), m_fetchActions); } void MainWindow::importFile(Import::Format format_, const KURL::List& urls_) { KURL::List urls = urls_; // update as DropHandler and Importer classes are updated if(urls_.count() > 1 && format_ != Import::Bibtex && format_ != Import::RIS && format_ != Import::PDF) { KURL u = urls_.front(); TQString url = u.isLocalFile() ? u.path() : u.prettyURL(); Kernel::self()->sorry(i18n("Tellico can only import one file of this type at a time. " "Only %1 will be imported.").arg(url)); urls.clear(); urls = u; } ImportDialog dlg(format_, urls, this, "importdlg"); if(dlg.exec() != TQDialog::Accepted) { return; } // if edit dialog is saved ok and if replacing, then the doc is saved ok if(m_editDialog->queryModified() && (dlg.action() != Import::Replace || Data::Document::self()->saveModified())) { GUI::CursorSaver cs(TQt::waitCursor); Data::CollPtr coll = dlg.collection(); if(!coll) { if(!dlg.statusMessage().isEmpty()) { Kernel::self()->sorry(dlg.statusMessage()); } return; } importCollection(coll, dlg.action()); } } bool MainWindow::importCollection(Data::CollPtr coll_, Import::Action action_) { bool failed = false; switch(action_) { case Import::Append: { // only append if match, but special case importing books into bibliographies Data::CollPtr c = Data::Document::self()->collection(); if(c->type() == coll_->type() || (c->type() == Data::Collection::Bibtex && coll_->type() == Data::Collection::Book)) { Kernel::self()->appendCollection(coll_); slotEnableModifiedActions(true); } else { Kernel::self()->sorry(i18n(errorAppendType)); failed = true; } } break; case Import::Merge: { // only merge if match, but special case importing books into bibliographies Data::CollPtr c = Data::Document::self()->collection(); if(c->type() == coll_->type() || (c->type() == Data::Collection::Bibtex && coll_->type() == Data::Collection::Book)) { Kernel::self()->mergeCollection(coll_); slotEnableModifiedActions(true); } else { Kernel::self()->sorry(i18n(errorMergeType)); failed = true; } } break; default: // replace Kernel::self()->replaceCollection(coll_); m_fileOpenRecent->setCurrentItem(-1); m_newDocument = true; slotEnableOpenedActions(); slotEnableModifiedActions(false); break; } return !failed; } void MainWindow::slotURLAction(const KURL& url_) { Q_ASSERT(url_.protocol() == Latin1Literal("tc")); TQString actionName = url_.fileName(); TDEAction* action = this->action(actionName); if(action) { action->activate(); } else { myWarning() << "MainWindow::slotURLAction() - unknown action: " << actionName << endl; } } bool MainWindow::eventFilter(TQObject* obj_, TQEvent* ev_) { if(ev_->type() == TQEvent::KeyPress && obj_ == m_quickFilter) { switch(static_cast(ev_)->key()) { case TQt::Key_Escape: m_quickFilter->clear(); return true; } } return false; } #include "mainwindow.moc"