/*************************************************************************** * Copyright (C) 2003 by Sébastien Laoût * * slaout@linux62.org * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ /// NEW: #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 #include #include #include "bnpview.h" #include "basket.h" #include "tools.h" #include "settings.h" #include "debugwindow.h" #include "xmlwork.h" #include "basketfactory.h" #include "softwareimporters.h" #include "colorpicker.h" #include "regiongrabber.h" #include "basketlistview.h" #include "basketproperties.h" #include "password.h" #include "newbasketdialog.h" #include "notedrag.h" #include "formatimporter.h" #include "basketstatusbar.h" #include "backgroundmanager.h" #include "noteedit.h" // To launch InlineEditors::initToolBars() #include "archive.h" #include "htmlexporter.h" #include "crashhandler.h" #include "likeback.h" #include "backup.h" /** class BNPView: */ const int BNPView::c_delayTooltipTime = 275; BNPView::BNPView(QWidget *parent, const char *name, KXMLGUIClient *aGUIClient, KActionCollection *actionCollection, BasketStatusBar *bar) : DCOPObject("BasketIface"), QSplitter(Qt::Horizontal, parent, name), m_actLockBasket(0), m_actPassBasket(0), m_loading(true), m_newBasketPopup(false), m_firstShow(true), m_regionGrabber(0), m_passiveDroppedSelection(0), m_passivePopup(0), m_actionCollection(actionCollection), m_guiClient(aGUIClient), m_statusbar(bar), m_tryHideTimer(0), m_hideTimer(0) { /* Settings */ Settings::loadConfig(); Global::bnpView = this; // Needed when loading the baskets: Global::globalAccel = new KGlobalAccel(this); // FIXME: might be null (KPart case)! Global::backgroundManager = new BackgroundManager(); setupGlobalShortcuts(); initialize(); QTimer::singleShot(0, this, SLOT(lateInit())); } BNPView::~BNPView() { int treeWidth = Global::bnpView->sizes()[Settings::treeOnLeft() ? 0 : 1]; Settings::setBasketTreeWidth(treeWidth); if (currentBasket() && currentBasket()->isDuringEdit()) currentBasket()->closeEditor(); Settings::saveConfig(); Global::bnpView = 0; delete Global::systemTray; Global::systemTray = 0; delete m_colorPicker; delete m_statusbar; NoteDrag::createAndEmptyCuttingTmpFolder(); // Clean the temporary folder we used } void BNPView::lateInit() { /* InlineEditors* instance = InlineEditors::instance(); if(instance) { KToolBar* toolbar = instance->richTextToolBar(); if(toolbar) toolbar->hide(); } */ if(!isPart()) { if (Settings::useSystray() && KCmdLineArgs::parsedArgs() && KCmdLineArgs::parsedArgs()->isSet("start-hidden")) if(Global::mainWindow()) Global::mainWindow()->hide(); else if (Settings::useSystray() && kapp->isRestored()) if(Global::mainWindow()) Global::mainWindow()->setShown(!Settings::startDocked()); else showMainWindow(); } // If the main window is hidden when session is saved, Container::queryClose() // isn't called and the last value would be kept Settings::setStartDocked(true); Settings::saveConfig(); /* System tray icon */ Global::systemTray = new SystemTray(Global::mainWindow()); connect( Global::systemTray, SIGNAL(showPart()), this, SIGNAL(showPart()) ); if (Settings::useSystray()) Global::systemTray->show(); // Load baskets DEBUG_WIN << "Baskets are loaded from " + Global::basketsFolder(); NoteDrag::createAndEmptyCuttingTmpFolder(); // If last exec hasn't done it: clean the temporary folder we will use Tag::loadTags(); // Tags should be ready before loading baskets, but tags need the mainContainer to be ready to create KActions! load(); // If no basket has been found, try to import from an older version, if (!firstListViewItem()) { QDir dir; dir.mkdir(Global::basketsFolder()); if (FormatImporter::shouldImportBaskets()) { FormatImporter::importBaskets(); load(); } if (!firstListViewItem()) { // Create first basket: BasketFactory::newBasket(/*icon=*/"", /*name=*/i18n("General"), /*backgroundImage=*/"", /*backgroundColor=*/QColor(), /*textColor=*/QColor(), /*templateName=*/"1column", /*createIn=*/0); } } // Load the Welcome Baskets if it is the First Time: if (!Settings::welcomeBasketsAdded()) { addWelcomeBaskets(); Settings::setWelcomeBasketsAdded(true); Settings::saveConfig(); } m_tryHideTimer = new QTimer(this); m_hideTimer = new QTimer(this); connect( m_tryHideTimer, SIGNAL(timeout()), this, SLOT(timeoutTryHide()) ); connect( m_hideTimer, SIGNAL(timeout()), this, SLOT(timeoutHide()) ); // Preload every baskets for instant filtering: /*StopWatch::start(100); QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); item->basket()->load(); kapp->processEvents(); ++it; } StopWatch::check(100);*/ } void BNPView::addWelcomeBaskets() { // Possible paths where to find the welcome basket archive, trying the translated one, and falling back to the English one: QStringList possiblePaths; if (QString(KGlobal::locale()->encoding()) == QString("UTF-8")) { // Welcome baskets are encoded in UTF-8. If the system is not, then use the English version: possiblePaths.append(KGlobal::dirs()->findResource("data", "basket/welcome/Welcome_" + KGlobal::locale()->language() + ".baskets")); possiblePaths.append(KGlobal::dirs()->findResource("data", "basket/welcome/Welcome_" + QStringList::split("_", KGlobal::locale()->language())[0] + ".baskets")); } possiblePaths.append(KGlobal::dirs()->findResource("data", "basket/welcome/Welcome_en_US.baskets")); // Take the first EXISTING basket archive found: QDir dir; QString path; for (QStringList::Iterator it = possiblePaths.begin(); it != possiblePaths.end(); ++it) { if (dir.exists(*it)) { path = *it; break; } } // Extract: if (!path.isEmpty()) Archive::open(path); } void BNPView::onFirstShow() { // Don't enable LikeBack until bnpview is shown. This way it works better with kontact. /* LikeBack */ /* Global::likeBack = new LikeBack(LikeBack::AllButtons, / *showBarByDefault=* /true, Global::config(), Global::about()); Global::likeBack->setServer("basket.linux62.org", "/likeback/send.php"); Global:likeBack->setAcceptedLanguages(QStringList::split(";", "en;fr"), i18n("Only english and french languages are accepted.")); if (isPart()) Global::likeBack->disableBar(); // See BNPView::shown() and BNPView::hide(). */ if (isPart()) Global::likeBack->disableBar(); // See BNPView::shown() and BNPView::hide(). /* LikeBack::init(Global::config(), Global::about(), LikeBack::AllButtons); LikeBack::setServer("basket.linux62.org", "/likeback/send.php"); // LikeBack::setServer("localhost", "/~seb/basket/likeback/send.php"); LikeBack::setCustomLanguageMessage(i18n("Only english and french languages are accepted.")); // LikeBack::setWindowNamesListing(LikeBack:: / *NoListing* / / *WarnUnnamedWindows* / AllWindows); */ // In late init, because we need kapp->mainWidget() to be set! if (!isPart()) connectTagsMenu(); m_statusbar->setupStatusBar(); int treeWidth = Settings::basketTreeWidth(); if (treeWidth < 0) treeWidth = m_tree->fontMetrics().maxWidth() * 11; QValueList splitterSizes; splitterSizes.append(treeWidth); setSizes(splitterSizes); } void BNPView::setupGlobalShortcuts() { /* Global shortcuts */ KGlobalAccel *globalAccel = Global::globalAccel; // Better for the following lines // Ctrl+Shift+W only works when started standalone: QWidget *basketMainWindow = (QWidget*) (Global::bnpView->parent()->inherits("MainWindow") ? Global::bnpView->parent() : 0); if (basketMainWindow) { globalAccel->insert( "global_show_hide_main_window", i18n("Show/hide main window"), i18n("Allows you to show main Window if it is hidden, and to hide it if it is shown."), Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_W, Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_W, basketMainWindow, SLOT(changeActive()), true, true ); } globalAccel->insert( "global_paste", i18n("Paste clipboard contents in current basket"), i18n("Allows you to paste clipboard contents in the current basket without having to open the main window."), Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_V, Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_V, Global::bnpView, SLOT(globalPasteInCurrentBasket()), true, true ); globalAccel->insert( "global_show_current_basket", i18n("Show current basket name"), i18n("Allows you to know basket is current without opening the main window."), "", "", Global::bnpView, SLOT(showPassiveContentForced()), true, true ); globalAccel->insert( "global_paste_selection", i18n("Paste selection in current basket"), i18n("Allows you to paste clipboard selection in the current basket without having to open the main window."), Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_S, Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_S, Global::bnpView, SLOT(pasteSelInCurrentBasket()), true, true ); globalAccel->insert( "global_new_basket", i18n("Create a new basket"), i18n("Allows you to create a new basket without having to open the main window (you then can use the other global shortcuts to add a note, paste clipboard or paste selection in this new basket)."), "", "", Global::bnpView, SLOT(askNewBasket()), true, true ); globalAccel->insert( "global_previous_basket", i18n("Go to previous basket"), i18n("Allows you to change current basket to the previous one without having to open the main window."), "", "", Global::bnpView, SLOT(goToPreviousBasket()), true, true ); globalAccel->insert( "global_next_basket", i18n("Go to next basket"), i18n("Allows you to change current basket to the next one without having to open the main window."), "", "", Global::bnpView, SLOT(goToNextBasket()), true, true ); // globalAccel->insert( "global_note_add_text", i18n("Insert plain text note"), // i18n("Add a plain text note to the current basket without having to open the main window."), // "", "", //Qt::CTRL+Qt::ALT+Qt::Key_T, Qt::CTRL+Qt::ALT+Qt::Key_T, // Global::bnpView, SLOT(addNoteText()), true, true ); globalAccel->insert( "global_note_add_html", i18n("Insert text note"), i18n("Add a text note to the current basket without having to open the main window."), Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_T, Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_T, //"", "", Global::bnpView, SLOT(addNoteHtml()), true, true ); globalAccel->insert( "global_note_add_image", i18n("Insert image note"), i18n("Add an image note to the current basket without having to open the main window."), "", "", Global::bnpView, SLOT(addNoteImage()), true, true ); globalAccel->insert( "global_note_add_link", i18n("Insert link note"), i18n("Add a link note to the current basket without having to open the main window."), "", "", Global::bnpView, SLOT(addNoteLink()), true, true ); globalAccel->insert( "global_note_add_color", i18n("Insert color note"), i18n("Add a color note to the current basket without having to open the main window."), "", "", Global::bnpView, SLOT(addNoteColor()), true, true ); globalAccel->insert( "global_note_pick_color", i18n("Pick color from screen"), i18n("Add a color note picked from one pixel on screen to the current basket without " "having to open the main window."), "", "", Global::bnpView, SLOT(slotColorFromScreenGlobal()), true, true ); globalAccel->insert( "global_note_grab_screenshot", i18n("Grab screen zone"), i18n("Grab a screen zone as an image in the current basket without " "having to open the main window."), "", "", Global::bnpView, SLOT(grabScreenshotGlobal()), true, true ); globalAccel->readSettings(); globalAccel->updateConnections(); } void BNPView::initialize() { /// Configure the List View Columns: m_tree = new BasketTreeListView(this); m_tree->addColumn(i18n("Baskets")); m_tree->setColumnWidthMode(0, QListView::Maximum); m_tree->setFullWidth(true); m_tree->setSorting(-1/*Disabled*/); m_tree->setRootIsDecorated(true); m_tree->setTreeStepSize(16); m_tree->setLineWidth(1); m_tree->setMidLineWidth(0); m_tree->setFocusPolicy(QWidget::NoFocus); /// Configure the List View Drag and Drop: m_tree->setDragEnabled(true); m_tree->setAcceptDrops(true); m_tree->setItemsMovable(true); m_tree->setDragAutoScroll(true); m_tree->setDropVisualizer(true); m_tree->setDropHighlighter(true); /// Configure the Splitter: m_stack = new QWidgetStack(this); setOpaqueResize(true); setCollapsible(m_tree, true); setCollapsible(m_stack, false); setResizeMode(m_tree, QSplitter::KeepSize); setResizeMode(m_stack, QSplitter::Stretch); /// Configure the List View Signals: connect( m_tree, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(slotPressed(QListViewItem*)) ); connect( m_tree, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotPressed(QListViewItem*)) ); connect( m_tree, SIGNAL(pressed(QListViewItem*)), this, SLOT(slotPressed(QListViewItem*)) ); connect( m_tree, SIGNAL(expanded(QListViewItem*)), this, SLOT(needSave(QListViewItem*)) ); connect( m_tree, SIGNAL(collapsed(QListViewItem*)), this, SLOT(needSave(QListViewItem*)) ); connect( m_tree, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) ); connect( m_tree, SIGNAL(mouseButtonPressed(int, QListViewItem*, const QPoint&, int)), this, SLOT(slotMouseButtonPressed(int, QListViewItem*, const QPoint&, int)) ); connect( m_tree, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)), this, SLOT(slotShowProperties(QListViewItem*, const QPoint&, int)) ); connect( m_tree, SIGNAL(expanded(QListViewItem*)), this, SIGNAL(basketChanged()) ); connect( m_tree, SIGNAL(collapsed(QListViewItem*)), this, SIGNAL(basketChanged()) ); connect( this, SIGNAL(basketNumberChanged(int)), this, SIGNAL(basketChanged()) ); connect( this, SIGNAL(basketNumberChanged(int)), this, SLOT(slotBasketNumberChanged(int)) ); connect( this, SIGNAL(basketChanged()), this, SLOT(slotBasketChanged()) ); /* LikeBack */ Global::likeBack = new LikeBack(LikeBack::AllButtons, /*showBarByDefault=*/false, Global::config(), Global::about()); Global::likeBack->setServer("basket.linux62.org", "/likeback/send.php"); // There are too much comments, and people reading comments are more and more international, so we accept only English: // Global::likeBack->setAcceptedLanguages(QStringList::split(";", "en;fr"), i18n("Please write in English or French.")); // if (isPart()) // Global::likeBack->disableBar(); // See BNPView::shown() and BNPView::hide(). Global::likeBack->sendACommentAction(actionCollection()); // Just create it! setupActions(); /// What's This Help for the tree: QWhatsThis::add(m_tree, i18n( "

Basket Tree

" "Here is the list of your baskets. " "You can organize your data by putting them in different baskets. " "You can group baskets by subject by creating new baskets inside others. " "You can browse between them by clicking a basket to open it, or reorganize them using drag and drop.")); setTreePlacement(Settings::treeOnLeft()); } void BNPView::setupActions() { m_actSaveAsArchive = new KAction( i18n("&Basket Archive..."), "baskets", 0, this, SLOT(saveAsArchive()), actionCollection(), "basket_export_basket_archive" ); m_actOpenArchive = new KAction( i18n("&Basket Archive..."), "baskets", 0, this, SLOT(openArchive()), actionCollection(), "basket_import_basket_archive" ); m_actHideWindow = new KAction( i18n("&Hide Window"), "", KStdAccel::shortcut(KStdAccel::Close), this, SLOT(hideOnEscape()), actionCollection(), "window_hide" ); m_actHideWindow->setEnabled(Settings::useSystray()); // Init here ! m_actExportToHtml = new KAction( i18n("&HTML Web Page..."), "html", 0, this, SLOT(exportToHTML()), actionCollection(), "basket_export_html" ); new KAction( i18n("K&Notes"), "knotes", 0, this, SLOT(importKNotes()), actionCollection(), "basket_import_knotes" ); new KAction( i18n("K&Jots"), "kjots", 0, this, SLOT(importKJots()), actionCollection(), "basket_import_kjots" ); new KAction( i18n("&KnowIt..."), "knowit", 0, this, SLOT(importKnowIt()), actionCollection(), "basket_import_knowit" ); new KAction( i18n("Tux&Cards..."), "tuxcards", 0, this, SLOT(importTuxCards()), actionCollection(), "basket_import_tuxcards" ); new KAction( i18n("&Sticky Notes"), "gnome", 0, this, SLOT(importStickyNotes()), actionCollection(), "basket_import_sticky_notes" ); new KAction( i18n("&Tomboy"), "tintin", 0, this, SLOT(importTomboy()), actionCollection(), "basket_import_tomboy" ); new KAction( i18n("Text &File..."), "txt", 0, this, SLOT(importTextFile()), actionCollection(), "basket_import_text_file" ); new KAction( i18n("&Backup && Restore..."), "", 0, this, SLOT(backupRestore()), actionCollection(), "basket_backup_restore" ); /** Note : ****************************************************************/ m_actDelNote = new KAction( i18n("D&elete"), "editdelete", "Delete", this, SLOT(delNote()), actionCollection(), "edit_delete" ); m_actCutNote = KStdAction::cut( this, SLOT(cutNote()), actionCollection() ); m_actCopyNote = KStdAction::copy( this, SLOT(copyNote()), actionCollection() ); m_actSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection() ); m_actSelectAll->setStatusText( i18n( "Selects all notes" ) ); m_actUnselectAll = new KAction( i18n( "U&nselect All" ), "", this, SLOT( slotUnselectAll() ), actionCollection(), "edit_unselect_all" ); m_actUnselectAll->setStatusText( i18n( "Unselects all selected notes" ) ); m_actInvertSelection = new KAction( i18n( "&Invert Selection" ), CTRL+Key_Asterisk, this, SLOT( slotInvertSelection() ), actionCollection(), "edit_invert_selection" ); m_actInvertSelection->setStatusText( i18n( "Inverts the current selection of notes" ) ); m_actEditNote = new KAction( i18n("Verb; not Menu", "&Edit..."), "edit", "Return", this, SLOT(editNote()), actionCollection(), "note_edit" ); m_actOpenNote = KStdAction::open( this, SLOT(openNote()), actionCollection(), "note_open" ); m_actOpenNote->setIcon("window_new"); m_actOpenNote->setText(i18n("&Open")); m_actOpenNote->setShortcut("F9"); m_actOpenNoteWith = new KAction( i18n("Open &With..."), "", "Shift+F9", this, SLOT(openNoteWith()), actionCollection(), "note_open_with" ); m_actSaveNoteAs = KStdAction::saveAs( this, SLOT(saveNoteAs()), actionCollection(), "note_save_to_file" ); m_actSaveNoteAs->setIcon(""); m_actSaveNoteAs->setText(i18n("&Save to File...")); m_actSaveNoteAs->setShortcut("F10"); m_actGroup = new KAction( i18n("&Group"), "attach", "Ctrl+G", this, SLOT(noteGroup()), actionCollection(), "note_group" ); m_actUngroup = new KAction( i18n("U&ngroup"), "", "Ctrl+Shift+G", this, SLOT(noteUngroup()), actionCollection(), "note_ungroup" ); m_actMoveOnTop = new KAction( i18n("Move on &Top"), "2uparrow", "Ctrl+Shift+Home", this, SLOT(moveOnTop()), actionCollection(), "note_move_top" ); m_actMoveNoteUp = new KAction( i18n("Move &Up"), "1uparrow", "Ctrl+Shift+Up", this, SLOT(moveNoteUp()), actionCollection(), "note_move_up" ); m_actMoveNoteDown = new KAction( i18n("Move &Down"), "1downarrow", "Ctrl+Shift+Down", this, SLOT(moveNoteDown()), actionCollection(), "note_move_down" ); m_actMoveOnBottom = new KAction( i18n("Move on &Bottom"), "2downarrow", "Ctrl+Shift+End", this, SLOT(moveOnBottom()), actionCollection(), "note_move_bottom" ); #if KDE_IS_VERSION( 3, 1, 90 ) // KDE 3.2.x m_actPaste = KStdAction::pasteText( this, SLOT(pasteInCurrentBasket()), actionCollection() ); #else m_actPaste = KStdAction::paste( this, SLOT(pasteInCurrentBasket()), actionCollection() ); #endif /** Insert : **************************************************************/ QSignalMapper *insertEmptyMapper = new QSignalMapper(this); QSignalMapper *insertWizardMapper = new QSignalMapper(this); connect( insertEmptyMapper, SIGNAL(mapped(int)), this, SLOT(insertEmpty(int)) ); connect( insertWizardMapper, SIGNAL(mapped(int)), this, SLOT(insertWizard(int)) ); // m_actInsertText = new KAction( i18n("Plai&n Text"), "text", "Ctrl+T", actionCollection(), "insert_text" ); m_actInsertHtml = new KAction( i18n("&Text"), "html", "Insert", actionCollection(), "insert_html" ); m_actInsertLink = new KAction( i18n("&Link"), "link", "Ctrl+Y", actionCollection(), "insert_link" ); m_actInsertImage = new KAction( i18n("&Image"), "image", "", actionCollection(), "insert_image" ); m_actInsertColor = new KAction( i18n("&Color"), "colorset", "", actionCollection(), "insert_color" ); m_actInsertLauncher=new KAction( i18n("L&auncher"), "launch", "", actionCollection(), "insert_launcher" ); m_actImportKMenu = new KAction( i18n("Import Launcher from &KDE Menu..."), "kmenu", "", actionCollection(), "insert_kmenu" ); m_actImportIcon = new KAction( i18n("Im&port Icon..."), "icons", "", actionCollection(), "insert_icon" ); m_actLoadFile = new KAction( i18n("Load From &File..."), "fileimport", "", actionCollection(), "insert_from_file" ); // connect( m_actInsertText, SIGNAL(activated()), insertEmptyMapper, SLOT(map()) ); connect( m_actInsertHtml, SIGNAL(activated()), insertEmptyMapper, SLOT(map()) ); connect( m_actInsertImage, SIGNAL(activated()), insertEmptyMapper, SLOT(map()) ); connect( m_actInsertLink, SIGNAL(activated()), insertEmptyMapper, SLOT(map()) ); connect( m_actInsertColor, SIGNAL(activated()), insertEmptyMapper, SLOT(map()) ); connect( m_actInsertLauncher, SIGNAL(activated()), insertEmptyMapper, SLOT(map()) ); // insertEmptyMapper->setMapping(m_actInsertText, NoteType::Text ); insertEmptyMapper->setMapping(m_actInsertHtml, NoteType::Html ); insertEmptyMapper->setMapping(m_actInsertImage, NoteType::Image ); insertEmptyMapper->setMapping(m_actInsertLink, NoteType::Link ); insertEmptyMapper->setMapping(m_actInsertColor, NoteType::Color ); insertEmptyMapper->setMapping(m_actInsertLauncher, NoteType::Launcher); connect( m_actImportKMenu, SIGNAL(activated()), insertWizardMapper, SLOT(map()) ); connect( m_actImportIcon, SIGNAL(activated()), insertWizardMapper, SLOT(map()) ); connect( m_actLoadFile, SIGNAL(activated()), insertWizardMapper, SLOT(map()) ); insertWizardMapper->setMapping(m_actImportKMenu, 1 ); insertWizardMapper->setMapping(m_actImportIcon, 2 ); insertWizardMapper->setMapping(m_actLoadFile, 3 ); m_colorPicker = new DesktopColorPicker(); m_actColorPicker = new KAction( i18n("C&olor from Screen"), "kcolorchooser", "", this, SLOT(slotColorFromScreen()), actionCollection(), "insert_screen_color" ); connect( m_colorPicker, SIGNAL(pickedColor(const QColor&)), this, SLOT(colorPicked(const QColor&)) ); connect( m_colorPicker, SIGNAL(canceledPick()), this, SLOT(colorPickingCanceled()) ); m_actGrabScreenshot = new KAction( i18n("Grab Screen &Zone"), "ksnapshot", "", this, SLOT(grabScreenshot()), actionCollection(), "insert_screen_capture" ); //connect( m_actGrabScreenshot, SIGNAL(regionGrabbed(const QPixmap&)), this, SLOT(screenshotGrabbed(const QPixmap&)) ); //connect( m_colorPicker, SIGNAL(canceledPick()), this, SLOT(colorPickingCanceled()) ); // m_insertActions.append( m_actInsertText ); m_insertActions.append( m_actInsertHtml ); m_insertActions.append( m_actInsertLink ); m_insertActions.append( m_actInsertImage ); m_insertActions.append( m_actInsertColor ); m_insertActions.append( m_actImportKMenu ); m_insertActions.append( m_actInsertLauncher ); m_insertActions.append( m_actImportIcon ); m_insertActions.append( m_actLoadFile ); m_insertActions.append( m_actColorPicker ); m_insertActions.append( m_actGrabScreenshot ); /** Basket : **************************************************************/ // At this stage, main.cpp has not set kapp->mainWidget(), so Global::runInsideKontact() // returns true. We do it ourself: bool runInsideKontact = true; QWidget *parentWidget = (QWidget*) parent(); while (parentWidget) { if (parentWidget->inherits("MainWindow")) runInsideKontact = false; parentWidget = (QWidget*) parentWidget->parent(); } // Use the "basket" incon in Kontact so it is consistent with the Kontact "New..." icon actNewBasket = new KAction( i18n("&New Basket..."), (runInsideKontact ? "basket" : "filenew"), KStdAccel::shortcut(KStdAccel::New), this, SLOT(askNewBasket()), actionCollection(), "basket_new" ); actNewSubBasket = new KAction( i18n("New &Sub-Basket..."), "", "Ctrl+Shift+N", this, SLOT(askNewSubBasket()), actionCollection(), "basket_new_sub" ); actNewSiblingBasket = new KAction( i18n("New Si&bling Basket..."), "", "", this, SLOT(askNewSiblingBasket()), actionCollection(), "basket_new_sibling" ); KActionMenu *newBasketMenu = new KActionMenu(i18n("&New"), "filenew", actionCollection(), "basket_new_menu"); newBasketMenu->insert(actNewBasket); newBasketMenu->insert(actNewSubBasket); newBasketMenu->insert(actNewSiblingBasket); connect( newBasketMenu, SIGNAL(activated()), this, SLOT(askNewBasket()) ); m_actPropBasket = new KAction( i18n("&Properties..."), "misc", "F2", this, SLOT(propBasket()), actionCollection(), "basket_properties" ); m_actDelBasket = new KAction( i18n("Remove Basket", "&Remove"), "", 0, this, SLOT(delBasket()), actionCollection(), "basket_remove" ); #ifdef HAVE_LIBGPGME m_actPassBasket = new KAction( i18n("Password protection", "Pass&word..."), "", 0, this, SLOT(password()), actionCollection(), "basket_password" ); m_actLockBasket = new KAction( i18n("Lock Basket", "&Lock"), "", "Ctrl+L", this, SLOT(lockBasket()), actionCollection(), "basket_lock" ); #endif /** Edit : ****************************************************************/ //m_actUndo = KStdAction::undo( this, SLOT(undo()), actionCollection() ); //m_actUndo->setEnabled(false); // Not yet implemented ! //m_actRedo = KStdAction::redo( this, SLOT(redo()), actionCollection() ); //m_actRedo->setEnabled(false); // Not yet implemented ! m_actShowFilter = new KToggleAction( i18n("&Filter"), "filter", KStdAccel::shortcut(KStdAccel::Find), actionCollection(), "edit_filter" ); connect( m_actShowFilter, SIGNAL(toggled(bool)), this, SLOT(showHideFilterBar(bool)) ); m_actFilterAllBaskets = new KToggleAction( i18n("Filter all &Baskets"), "find", "Ctrl+Shift+F", actionCollection(), "edit_filter_all_baskets" ); connect( m_actFilterAllBaskets, SIGNAL(toggled(bool)), this, SLOT(toggleFilterAllBaskets(bool)) ); m_actResetFilter = new KAction( i18n( "&Reset Filter" ), "locationbar_erase", "Ctrl+R", this, SLOT( slotResetFilter() ), actionCollection(), "edit_filter_reset" ); /** Go : ******************************************************************/ m_actPreviousBasket = new KAction( i18n( "&Previous Basket" ), "up", "Alt+Up", this, SLOT(goToPreviousBasket()), actionCollection(), "go_basket_previous" ); m_actNextBasket = new KAction( i18n( "&Next Basket" ), "down", "Alt+Down", this, SLOT(goToNextBasket()), actionCollection(), "go_basket_next" ); m_actFoldBasket = new KAction( i18n( "&Fold Basket" ), "back", "Alt+Left", this, SLOT(foldBasket()), actionCollection(), "go_basket_fold" ); m_actExpandBasket = new KAction( i18n( "&Expand Basket" ), "forward", "Alt+Right", this, SLOT(expandBasket()), actionCollection(), "go_basket_expand" ); // FOR_BETA_PURPOSE: // m_convertTexts = new KAction( i18n("Convert text notes to rich text notes"), "compfile", "", // this, SLOT(convertTexts()), actionCollection(), "beta_convert_texts" ); InlineEditors::instance()->initToolBars(actionCollection()); actConfigGlobalShortcuts = KStdAction::keyBindings(this, SLOT(showGlobalShortcutsSettingsDialog()), actionCollection(), "options_configure_global_keybinding"); actConfigGlobalShortcuts->setText(i18n("Configure &Global Shortcuts...")); /** Help : ****************************************************************/ new KAction( i18n("&Welcome Baskets"), "", "", this, SLOT(addWelcomeBaskets()), actionCollection(), "help_welcome_baskets" ); } QListViewItem* BNPView::firstListViewItem() { return m_tree->firstChild(); } void BNPView::slotShowProperties(QListViewItem *item, const QPoint&, int) { if (item) propBasket(); } void BNPView::slotMouseButtonPressed(int button, QListViewItem *item, const QPoint &/*pos*/, int /*column*/) { if (item && (button & Qt::MidButton)) { // TODO: Paste into ((BasketListViewItem*)listViewItem)->basket() } } void BNPView::slotContextMenu(KListView */*listView*/, QListViewItem *item, const QPoint &pos) { QString menuName; if (item) { Basket* basket = ((BasketListViewItem*)item)->basket(); setCurrentBasket(basket); menuName = "basket_popup"; } else { menuName = "tab_bar_popup"; /* * "File -> New" create a new basket with the same parent basket as the the current one. * But when invoked when right-clicking the empty area at the bottom of the basket tree, * it is obvious the user want to create a new basket at the bottom of the tree (with no parent). * So we set a temporary variable during the time the popup menu is shown, * so the slot askNewBasket() will do the right thing: */ setNewBasketPopup(); } QPopupMenu *menu = popupMenu(menuName); connect( menu, SIGNAL(aboutToHide()), this, SLOT(aboutToHideNewBasketPopup()) ); menu->exec(pos); } void BNPView::save() { DEBUG_WIN << "Basket Tree: Saving..."; // Create Document: QDomDocument document("basketTree"); QDomElement root = document.createElement("basketTree"); document.appendChild(root); // Save Basket Tree: save(m_tree->firstChild(), document, root); // Write to Disk: Basket::safelySaveToFile(Global::basketsFolder() + "baskets.xml", "\n" + document.toString()); // QFile file(Global::basketsFolder() + "baskets.xml"); // if (file.open(IO_WriteOnly)) { // QTextStream stream(&file); // stream.setEncoding(QTextStream::UnicodeUTF8); // QString xml = document.toString(); // stream << "\n"; // stream << xml; // file.close(); // } } void BNPView::save(QListViewItem *firstItem, QDomDocument &document, QDomElement &parentElement) { QListViewItem *item = firstItem; while (item) { // Basket *basket = ((BasketListViewItem*)item)->basket(); QDomElement basketElement = this->basketElement(item, document, parentElement); /* QDomElement basketElement = document.createElement("basket"); parentElement.appendChild(basketElement); // Save Attributes: basketElement.setAttribute("folderName", basket->folderName()); if (item->firstChild()) // If it can be expanded/folded: basketElement.setAttribute("folded", XMLWork::trueOrFalse(!item->isOpen())); if (((BasketListViewItem*)item)->isCurrentBasket()) basketElement.setAttribute("lastOpened", "true"); // Save Properties: QDomElement properties = document.createElement("properties"); basketElement.appendChild(properties); basket->saveProperties(document, properties); */ // Save Child Basket: if (item->firstChild()) save(item->firstChild(), document, basketElement); // Next Basket: item = item->nextSibling(); } } QDomElement BNPView::basketElement(QListViewItem *item, QDomDocument &document, QDomElement &parentElement) { Basket *basket = ((BasketListViewItem*)item)->basket(); QDomElement basketElement = document.createElement("basket"); parentElement.appendChild(basketElement); // Save Attributes: basketElement.setAttribute("folderName", basket->folderName()); if (item->firstChild()) // If it can be expanded/folded: basketElement.setAttribute("folded", XMLWork::trueOrFalse(!item->isOpen())); if (((BasketListViewItem*)item)->isCurrentBasket()) basketElement.setAttribute("lastOpened", "true"); // Save Properties: QDomElement properties = document.createElement("properties"); basketElement.appendChild(properties); basket->saveProperties(document, properties); return basketElement; } void BNPView::saveSubHierarchy(QListViewItem *item, QDomDocument &document, QDomElement &parentElement, bool recursive) { QDomElement element = basketElement(item, document, parentElement); if (recursive && item->firstChild()) save(item->firstChild(), document, element); } void BNPView::load() { QDomDocument *doc = XMLWork::openFile("basketTree", Global::basketsFolder() + "baskets.xml"); //BEGIN Compatibility with 0.6.0 Pre-Alpha versions: if (!doc) doc = XMLWork::openFile("basketsTree", Global::basketsFolder() + "baskets.xml"); //END if (doc != 0) { QDomElement docElem = doc->documentElement(); load(m_tree, 0L, docElem); } m_loading = false; } void BNPView::load(KListView */*listView*/, QListViewItem *item, const QDomElement &baskets) { QDomNode n = baskets.firstChild(); while ( ! n.isNull() ) { QDomElement element = n.toElement(); if ( (!element.isNull()) && element.tagName() == "basket" ) { QString folderName = element.attribute("folderName"); if (!folderName.isEmpty()) { Basket *basket = loadBasket(folderName); BasketListViewItem *basketItem = appendBasket(basket, item); basketItem->setOpen(!XMLWork::trueOrFalse(element.attribute("folded", "false"), false)); basket->loadProperties(XMLWork::getElement(element, "properties")); if (XMLWork::trueOrFalse(element.attribute("lastOpened", element.attribute("lastOpenned", "false")), false)) // Compat with 0.6.0-Alphas setCurrentBasket(basket); // Load Sub-baskets: load(/*(QListView*)*/0L, basketItem, element); } } n = n.nextSibling(); } } Basket* BNPView::loadBasket(const QString &folderName) { if (folderName.isEmpty()) return 0; DecoratedBasket *decoBasket = new DecoratedBasket(m_stack, folderName); Basket *basket = decoBasket->basket(); m_stack->addWidget(decoBasket); connect( basket, SIGNAL(countsChanged(Basket*)), this, SLOT(countsChanged(Basket*)) ); // Important: Create listViewItem and connect signal BEFORE loadProperties(), so we get the listViewItem updated without extra work: connect( basket, SIGNAL(propertiesChanged(Basket*)), this, SLOT(updateBasketListViewItem(Basket*)) ); connect( basket->decoration()->filterBar(), SIGNAL(newFilter(const FilterData&)), this, SLOT(newFilterFromFilterBar()) ); return basket; } int BNPView::basketCount(QListViewItem *parent) { int count = 0; QListViewItem *item = (parent ? parent->firstChild() : m_tree->firstChild()); while (item) { count += 1 + basketCount(item); item = item->nextSibling(); } return count; } bool BNPView::canFold() { BasketListViewItem *item = listViewItemForBasket(currentBasket()); if (!item) return false; return item->parent() || (item->firstChild() && item->isOpen()); } bool BNPView::canExpand() { BasketListViewItem *item = listViewItemForBasket(currentBasket()); if (!item) return false; return item->firstChild(); } BasketListViewItem* BNPView::appendBasket(Basket *basket, QListViewItem *parentItem) { BasketListViewItem *newBasketItem; if (parentItem) newBasketItem = new BasketListViewItem(parentItem, ((BasketListViewItem*)parentItem)->lastChild(), basket); else { QListViewItem *child = m_tree->firstChild(); QListViewItem *lastChild = 0; while (child) { lastChild = child; child = child->nextSibling(); } newBasketItem = new BasketListViewItem(m_tree, lastChild, basket); } emit basketNumberChanged(basketCount()); return newBasketItem; } void BNPView::loadNewBasket(const QString &folderName, const QDomElement &properties, Basket *parent) { Basket *basket = loadBasket(folderName); appendBasket(basket, (basket ? listViewItemForBasket(parent) : 0)); basket->loadProperties(properties); setCurrentBasket(basket); // save(); } BasketListViewItem* BNPView::lastListViewItem() { QListViewItem *child = m_tree->firstChild(); QListViewItem *lastChild = 0; // Set lastChild to the last primary child of the list view: while (child) { lastChild = child; child = child->nextSibling(); } // If this child have child(s), recursivly browse through them to find the real last one: while (lastChild && lastChild->firstChild()) { child = lastChild->firstChild(); while (child) { lastChild = child; child = child->nextSibling(); } } return (BasketListViewItem*)lastChild; } void BNPView::goToPreviousBasket() { if (!m_tree->firstChild()) return; BasketListViewItem *item = listViewItemForBasket(currentBasket()); BasketListViewItem *toSwitch = item->shownItemAbove(); if (!toSwitch) { toSwitch = lastListViewItem(); if (toSwitch && !toSwitch->isShown()) toSwitch = toSwitch->shownItemAbove(); } if (toSwitch) setCurrentBasket(toSwitch->basket()); if (Settings::usePassivePopup()) showPassiveContent(); } void BNPView::goToNextBasket() { if (!m_tree->firstChild()) return; BasketListViewItem *item = listViewItemForBasket(currentBasket()); BasketListViewItem *toSwitch = item->shownItemBelow(); if (!toSwitch) toSwitch = ((BasketListViewItem*)m_tree->firstChild()); if (toSwitch) setCurrentBasket(toSwitch->basket()); if (Settings::usePassivePopup()) showPassiveContent(); } void BNPView::foldBasket() { BasketListViewItem *item = listViewItemForBasket(currentBasket()); if (item && !item->firstChild()) item->setOpen(false); // If Alt+Left is hitted and there is nothing to close, make sure the focus will go to the parent basket QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, 0, 0); QApplication::postEvent(m_tree, keyEvent); } void BNPView::expandBasket() { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, 0, 0); QApplication::postEvent(m_tree, keyEvent); } void BNPView::closeAllEditors() { QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = (BasketListViewItem*)(it.current()); item->basket()->closeEditor(); ++it; } } bool BNPView::convertTexts() { bool convertedNotes = false; KProgressDialog dialog( /*parent=*/0, /*name=*/"", /*caption=*/i18n("Plain Text Notes Conversion"), /*text=*/i18n("Converting plain text notes to rich text ones..."), /*modal=*/true); dialog.progressBar()->setTotalSteps(basketCount()); dialog.show(); //setMinimumDuration(50/*ms*/); QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = (BasketListViewItem*)(it.current()); if (item->basket()->convertTexts()) convertedNotes = true; dialog.progressBar()->advance(1); if (dialog.wasCancelled()) break; ++it; } return convertedNotes; } /** isRunning is to avoid recursive calls because this method can be called * when clicking the menu action or when using the filter-bar icon... either of those calls * call the other to be checked... and it can cause recursive calls. * PS: Uggly hack? Yes, I think so :-) */ void BNPView::toggleFilterAllBaskets(bool doFilter) { static bool isRunning = false; if (isRunning) return; isRunning = true; // Set the state: m_actFilterAllBaskets->setChecked(doFilter); //currentBasket()->decoration()->filterBar()->setFilterAll(doFilter); // Basket *current = currentBasket(); QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); item->basket()->decoration()->filterBar()->setFilterAll(doFilter); ++it; } // Protection is not necessary anymore: isRunning = false; if (doFilter) currentBasket()->decoration()->filterBar()->setEditFocus(); // Filter every baskets: newFilter(); } /** This function can be called recursively because we call kapp->processEvents(). * If this function is called whereas another "instance" is running, * this new "instance" leave and set up a flag that is read by the first "instance" * to know it should re-begin the work. * PS: Yes, that's a very lame pseudo-threading but that works, and it's programmer-efforts cheap :-) */ void BNPView::newFilter() { static bool alreadyEntered = false; static bool shouldRestart = false; if (alreadyEntered) { shouldRestart = true; return; } alreadyEntered = true; shouldRestart = false; Basket *current = currentBasket(); const FilterData &filterData = current->decoration()->filterBar()->filterData(); // Set the filter data for every other baskets, or reset the filter for every other baskets if we just disabled the filterInAllBaskets: QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); if (item->basket() != current) if (isFilteringAllBaskets()) item->basket()->decoration()->filterBar()->setFilterData(filterData); // Set the new FilterData for every other baskets else item->basket()->decoration()->filterBar()->setFilterData(FilterData()); // We just disabled the global filtering: remove the FilterData ++it; } // Show/hide the "little filter icons" (during basket load) // or the "little numbers" (to show number of found notes in the baskets) is the tree: m_tree->triggerUpdate(); kapp->processEvents(); // Load every baskets for filtering, if they are not already loaded, and if necessary: if (filterData.isFiltering) { Basket *current = currentBasket(); QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); if (item->basket() != current) { Basket *basket = item->basket(); if (!basket->loadingLaunched() && !basket->isLocked()) basket->load(); basket->filterAgain(); m_tree->triggerUpdate(); kapp->processEvents(); if (shouldRestart) { alreadyEntered = false; shouldRestart = false; newFilter(); return; } } ++it; } } m_tree->triggerUpdate(); // kapp->processEvents(); alreadyEntered = false; shouldRestart = false; } void BNPView::newFilterFromFilterBar() { if (isFilteringAllBaskets()) QTimer::singleShot(0, this, SLOT(newFilter())); // Keep time for the QLineEdit to display the filtered character and refresh correctly! } bool BNPView::isFilteringAllBaskets() { return m_actFilterAllBaskets->isChecked(); } BasketListViewItem* BNPView::listViewItemForBasket(Basket *basket) { QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); if (item->basket() == basket) return item; ++it; } return 0L; } Basket* BNPView::currentBasket() { DecoratedBasket *decoBasket = (DecoratedBasket*)m_stack->visibleWidget(); if (decoBasket) return decoBasket->basket(); else return 0; } Basket* BNPView::parentBasketOf(Basket *basket) { BasketListViewItem *item = (BasketListViewItem*)(listViewItemForBasket(basket)->parent()); if (item) return item->basket(); else return 0; } void BNPView::setCurrentBasket(Basket *basket) { if (currentBasket() == basket) return; if (currentBasket()) currentBasket()->closeBasket(); if (basket) basket->aboutToBeActivated(); BasketListViewItem *item = listViewItemForBasket(basket); if (item) { m_tree->setSelected(item, true); item->ensureVisible(); m_stack->raiseWidget(basket->decoration()); // If the window has changed size, only the current basket receive the event, // the others will receive ony one just before they are shown. // But this triggers unwanted animations, so we eliminate it: basket->relayoutNotes(/*animate=*/false); basket->openBasket(); setCaption(item->basket()->basketName()); countsChanged(basket); updateStatusBarHint(); if (Global::systemTray) Global::systemTray->updateToolTip(); m_tree->ensureItemVisible(m_tree->currentItem()); item->basket()->setFocus(); } m_tree->viewport()->update(); emit basketChanged(); } void BNPView::removeBasket(Basket *basket) { if (basket->isDuringEdit()) basket->closeEditor(); // Find a new basket to switch to and select it. // Strategy: get the next sibling, or the previous one if not found. // If there is no such one, get the parent basket: BasketListViewItem *basketItem = listViewItemForBasket(basket); BasketListViewItem *nextBasketItem = (BasketListViewItem*)(basketItem->nextSibling()); if (!nextBasketItem) nextBasketItem = basketItem->prevSibling(); if (!nextBasketItem) nextBasketItem = (BasketListViewItem*)(basketItem->parent()); if (nextBasketItem) setCurrentBasket(nextBasketItem->basket()); // Remove from the view: basket->unsubscribeBackgroundImages(); m_stack->removeWidget(basket->decoration()); // delete basket->decoration(); delete basketItem; // delete basket; // If there is no basket anymore, add a new one: if (!nextBasketItem) BasketFactory::newBasket(/*icon=*/"", /*name=*/i18n("General"), /*backgroundImage=*/"", /*backgroundColor=*/QColor(), /*textColor=*/QColor(), /*templateName=*/"1column", /*createIn=*/0); else // No need to save two times if we add a basket save(); emit basketNumberChanged(basketCount()); } void BNPView::setTreePlacement(bool onLeft) { if (onLeft) moveToFirst(m_tree); else moveToLast(m_tree); //updateGeometry(); kapp->postEvent( this, new QResizeEvent(size(), size()) ); } void BNPView::relayoutAllBaskets() { QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); //item->basket()->unbufferizeAll(); item->basket()->unsetNotesWidth(); item->basket()->relayoutNotes(true); ++it; } } void BNPView::recomputeAllStyles() { QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); item->basket()->recomputeAllStyles(); item->basket()->unsetNotesWidth(); item->basket()->relayoutNotes(true); ++it; } } void BNPView::removedStates(const QValueList &deletedStates) { QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); item->basket()->removedStates(deletedStates); ++it; } } void BNPView::linkLookChanged() { QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = ((BasketListViewItem*)it.current()); item->basket()->linkLookChanged(); ++it; } } void BNPView::filterPlacementChanged(bool onTop) { QListViewItemIterator it(m_tree); while (it.current()) { BasketListViewItem *item = static_cast(it.current()); DecoratedBasket *decoration = static_cast(item->basket()->parent()); decoration->setFilterBarPosition(onTop); ++it; } } void BNPView::updateBasketListViewItem(Basket *basket) { BasketListViewItem *item = listViewItemForBasket(basket); if (item) item->setup(); if (basket == currentBasket()) { setCaption(basket->basketName()); if (Global::systemTray) Global::systemTray->updateToolTip(); } // Don't save if we are loading! if (!m_loading) save(); } void BNPView::needSave(QListViewItem*) { if (!m_loading) // A basket has been collapsed/expanded or a new one is select: this is not urgent: QTimer::singleShot(500/*ms*/, this, SLOT(save())); } void BNPView::slotPressed(QListViewItem *item, const QPoint &/*pos*/, int /*column*/) { Basket *basket = currentBasket(); if (basket == 0) return; // Impossible to Select no Basket: if (!item) m_tree->setSelected(listViewItemForBasket(basket), true); else if (dynamic_cast(item) != 0 && currentBasket() != ((BasketListViewItem*)item)->basket()) { setCurrentBasket( ((BasketListViewItem*)item)->basket() ); needSave(0); } basket->setFocus(); } DecoratedBasket* BNPView::currentDecoratedBasket() { if (currentBasket()) return currentBasket()->decoration(); else return 0; } // Redirected actions : void BNPView::exportToHTML() { HTMLExporter exporter(currentBasket()); } void BNPView::editNote() { currentBasket()->noteEdit(); } void BNPView::cutNote() { currentBasket()->noteCut(); } void BNPView::copyNote() { currentBasket()->noteCopy(); } void BNPView::delNote() { currentBasket()->noteDelete(); } void BNPView::openNote() { currentBasket()->noteOpen(); } void BNPView::openNoteWith() { currentBasket()->noteOpenWith(); } void BNPView::saveNoteAs() { currentBasket()->noteSaveAs(); } void BNPView::noteGroup() { currentBasket()->noteGroup(); } void BNPView::noteUngroup() { currentBasket()->noteUngroup(); } void BNPView::moveOnTop() { currentBasket()->noteMoveOnTop(); } void BNPView::moveOnBottom() { currentBasket()->noteMoveOnBottom(); } void BNPView::moveNoteUp() { currentBasket()->noteMoveNoteUp(); } void BNPView::moveNoteDown() { currentBasket()->noteMoveNoteDown(); } void BNPView::slotSelectAll() { currentBasket()->selectAll(); } void BNPView::slotUnselectAll() { currentBasket()->unselectAll(); } void BNPView::slotInvertSelection() { currentBasket()->invertSelection(); } void BNPView::slotResetFilter() { currentDecoratedBasket()->resetFilter(); } void BNPView::importKJots() { SoftwareImporters::importKJots(); } void BNPView::importKNotes() { SoftwareImporters::importKNotes(); } void BNPView::importKnowIt() { SoftwareImporters::importKnowIt(); } void BNPView::importTuxCards() { SoftwareImporters::importTuxCards(); } void BNPView::importStickyNotes() { SoftwareImporters::importStickyNotes(); } void BNPView::importTomboy() { SoftwareImporters::importTomboy(); } void BNPView::importTextFile() { SoftwareImporters::importTextFile(); } void BNPView::backupRestore() { BackupDialog dialog; dialog.exec(); } void BNPView::countsChanged(Basket *basket) { if (basket == currentBasket()) notesStateChanged(); } void BNPView::notesStateChanged() { Basket *basket = currentBasket(); // Update statusbar message : if (currentBasket()->isLocked()) setSelectionStatus(i18n("Locked")); else if (!basket->isLoaded()) setSelectionStatus(i18n("Loading...")); else if (basket->count() == 0) setSelectionStatus(i18n("No notes")); else { QString count = i18n("%n note", "%n notes", basket->count() ); QString selecteds = i18n("%n selected", "%n selected", basket->countSelecteds()); QString showns = (currentDecoratedBasket()->filterData().isFiltering ? i18n("all matches") : i18n("no filter")); if (basket->countFounds() != basket->count()) showns = i18n("%n match", "%n matches", basket->countFounds()); setSelectionStatus( i18n("e.g. '18 notes, 10 matches, 5 selected'", "%1, %2, %3").arg(count, showns, selecteds) ); } // If we added a note that match the global filter, update the count number in the tree: if (isFilteringAllBaskets()) listViewItemForBasket(basket)->listView()->triggerUpdate(); if (currentBasket()->redirectEditActions()) { m_actSelectAll ->setEnabled( !currentBasket()->selectedAllTextInEditor() ); m_actUnselectAll ->setEnabled( currentBasket()->hasSelectedTextInEditor() ); } else { m_actSelectAll ->setEnabled( basket->countSelecteds() < basket->countFounds() ); m_actUnselectAll ->setEnabled( basket->countSelecteds() > 0 ); } m_actInvertSelection ->setEnabled( basket->countFounds() > 0 ); updateNotesActions(); } void BNPView::updateNotesActions() { bool isLocked = currentBasket()->isLocked(); bool oneSelected = currentBasket()->countSelecteds() == 1; bool oneOrSeveralSelected = currentBasket()->countSelecteds() >= 1; bool severalSelected = currentBasket()->countSelecteds() >= 2; // FIXME: m_actCheckNotes is also modified in void BNPView::areSelectedNotesCheckedChanged(bool checked) // bool Basket::areSelectedNotesChecked() should return false if bool Basket::showCheckBoxes() is false // m_actCheckNotes->setChecked( oneOrSeveralSelected && // currentBasket()->areSelectedNotesChecked() && // currentBasket()->showCheckBoxes() ); Note *selectedGroup = (severalSelected ? currentBasket()->selectedGroup() : 0); m_actEditNote ->setEnabled( !isLocked && oneSelected && !currentBasket()->isDuringEdit() ); if (currentBasket()->redirectEditActions()) { m_actCutNote ->setEnabled( currentBasket()->hasSelectedTextInEditor() ); m_actCopyNote ->setEnabled( currentBasket()->hasSelectedTextInEditor() ); m_actPaste ->setEnabled( true ); m_actDelNote ->setEnabled( currentBasket()->hasSelectedTextInEditor() ); } else { m_actCutNote ->setEnabled( !isLocked && oneOrSeveralSelected ); m_actCopyNote ->setEnabled( oneOrSeveralSelected ); m_actPaste ->setEnabled( !isLocked ); m_actDelNote ->setEnabled( !isLocked && oneOrSeveralSelected ); } m_actOpenNote ->setEnabled( oneOrSeveralSelected ); m_actOpenNoteWith ->setEnabled( oneSelected ); // TODO: oneOrSeveralSelected IF SAME TYPE m_actSaveNoteAs ->setEnabled( oneSelected ); // IDEM? m_actGroup ->setEnabled( !isLocked && severalSelected && (!selectedGroup || selectedGroup->isColumn()) ); m_actUngroup ->setEnabled( !isLocked && selectedGroup && !selectedGroup->isColumn() ); m_actMoveOnTop ->setEnabled( !isLocked && oneOrSeveralSelected && !currentBasket()->isFreeLayout() ); m_actMoveNoteUp ->setEnabled( !isLocked && oneOrSeveralSelected ); // TODO: Disable when unavailable! m_actMoveNoteDown ->setEnabled( !isLocked && oneOrSeveralSelected ); m_actMoveOnBottom ->setEnabled( !isLocked && oneOrSeveralSelected && !currentBasket()->isFreeLayout() ); for (KAction *action = m_insertActions.first(); action; action = m_insertActions.next()) action->setEnabled( !isLocked ); // From the old Note::contextMenuEvent(...) : /* if (useFile() || m_type == Link) { m_type == Link ? i18n("&Open target") : i18n("&Open") m_type == Link ? i18n("Open target &with...") : i18n("Open &with...") m_type == Link ? i18n("&Save target as...") : i18n("&Save a copy as...") // If useFile() theire is always a file to open / open with / save, but : if (m_type == Link) { if (url().prettyURL().isEmpty() && runCommand().isEmpty()) // no URL nor runCommand : popupMenu->setItemEnabled(7, false); // no possible Open ! if (url().prettyURL().isEmpty()) // no URL : popupMenu->setItemEnabled(8, false); // no possible Open with ! if (url().prettyURL().isEmpty() || url().path().endsWith("/")) // no URL or target a folder : popupMenu->setItemEnabled(9, false); // not possible to save target file } } else if (m_type != Color) { popupMenu->insertSeparator(); popupMenu->insertItem( SmallIconSet("filesaveas"), i18n("&Save a copy as..."), this, SLOT(slotSaveAs()), 0, 10 ); }*/ } // BEGIN Color picker (code from KColorEdit): /* Activate the mode */ void BNPView::slotColorFromScreen(bool global) { m_colorPickWasGlobal = global; if (isMainWindowActive()) { if(Global::mainWindow()) Global::mainWindow()->hide(); m_colorPickWasShown = true; } else m_colorPickWasShown = false; currentBasket()->saveInsertionData(); m_colorPicker->pickColor(); /* m_gettingColorFromScreen = true; kapp->processEvents(); QTimer::singleShot( 100, this, SLOT(grabColorFromScreen()) );*/ } void BNPView::slotColorFromScreenGlobal() { slotColorFromScreen(true); } void BNPView::colorPicked(const QColor &color) { if (!currentBasket()->isLoaded()) { showPassiveLoading(currentBasket()); currentBasket()->load(); } currentBasket()->insertColor(color); if (m_colorPickWasShown) showMainWindow(); if (Settings::usePassivePopup()) showPassiveDropped(i18n("Picked color to basket %1")); } void BNPView::colorPickingCanceled() { if (m_colorPickWasShown) showMainWindow(); } void BNPView::slotConvertTexts() { /* int result = KMessageBox::questionYesNoCancel( this, i18n( "

This will convert every text notes into rich text notes.
" "The content of the notes will not change and you will be able to apply formating to those notes.

" "

This process cannot be reverted back: you will not be able to convert the rich text notes to plain text ones later.

" "

As a beta-tester, you are strongly encouraged to do the convert process because it is to test if plain text notes are still needed.
" "If nobody complain about not having plain text notes anymore, then the final version is likely to not support plain text notes anymore.

" "

Which basket notes do you want to convert?

" ), i18n("Convert Text Notes"), KGuiItem(i18n("Only in the Current Basket")), KGuiItem(i18n("In Every Baskets")) ); if (result == KMessageBox::Cancel) return; */ bool conversionsDone; // if (result == KMessageBox::Yes) // conversionsDone = currentBasket()->convertTexts(); // else conversionsDone = convertTexts(); if (conversionsDone) KMessageBox::information(this, i18n("The plain text notes have been converted to rich text."), i18n("Conversion Finished")); else KMessageBox::information(this, i18n("There are no plain text notes to convert."), i18n("Conversion Finished")); } QPopupMenu* BNPView::popupMenu(const QString &menuName) { QPopupMenu *menu = 0; bool hack = false; // TODO fix this // When running in kontact and likeback Information message is shown // factory is 0. Don't show error then and don't crash either :-) if(m_guiClient) { KXMLGUIFactory* factory = m_guiClient->factory(); if(factory) { menu = (QPopupMenu *)factory->container(menuName, m_guiClient); } else hack = isPart(); } if (menu == 0) { if(!hack) { KStandardDirs stdDirs; KMessageBox::error( this, i18n( "

The file basketui.rc seems to not exist or is too old.
" "%1 cannot run without it and will stop.

" "

Please check your installation of %2.

" "

If you do not have administrator access to install the application " "system wide, you can copy the file basketui.rc from the installation " "archive to the folder %4.

" "

As last ressort, if you are sure the application is correctly installed " "but you had a preview version of it, try to remove the " "file %5basketui.rc

") .arg(kapp->aboutData()->programName(), kapp->aboutData()->programName(), stdDirs.saveLocation("data", "basket/")).arg(stdDirs.saveLocation("data", "basket/"), stdDirs.saveLocation("data", "basket/")), i18n("Ressource not Found"), KMessageBox::AllowLink ); } if(!isPart()) exit(1); // We SHOULD exit right now and abord everything because the caller except menu != 0 to not crash. else menu = new KPopupMenu; // When running in kpart we cannot exit } return menu; } void BNPView::showHideFilterBar(bool show, bool switchFocus) { // if (show != m_actShowFilter->isChecked()) // m_actShowFilter->setChecked(show); m_actShowFilter->setChecked(currentDecoratedBasket()->filterData().isFiltering); currentDecoratedBasket()->setFilterBarShown(show, switchFocus); currentDecoratedBasket()->resetFilter(); } void BNPView::insertEmpty(int type) { if (currentBasket()->isLocked()) { showPassiveImpossible(i18n("Cannot add note.")); return; } currentBasket()->insertEmptyNote(type); } void BNPView::insertWizard(int type) { if (currentBasket()->isLocked()) { showPassiveImpossible(i18n("Cannot add note.")); return; } currentBasket()->insertWizard(type); } // BEGIN Screen Grabbing: // FIXME void BNPView::grabScreenshot(bool global) { if (m_regionGrabber) { KWin::activateWindow(m_regionGrabber->winId()); return; } // Delay before to take a screenshot because if we hide the main window OR the systray popup menu, // we should wait the windows below to be repainted!!! // A special case is where the action is triggered with the global keyboard shortcut. // In this case, global is true, and we don't wait. // In the future, if global is also defined for other cases, check for // enum KAction::ActivationReason { UnknownActivation, EmulatedActivation, AccelActivation, PopupMenuActivation, ToolBarActivation }; int delay = (isMainWindowActive() ? 500 : (global/*kapp->activePopupWidget()*/ ? 0 : 200)); m_colorPickWasGlobal = global; if (isMainWindowActive()) { if(Global::mainWindow()) Global::mainWindow()->hide(); m_colorPickWasShown = true; } else m_colorPickWasShown = false; currentBasket()->saveInsertionData(); m_regionGrabber = new RegionGrabber(delay); connect( m_regionGrabber, SIGNAL(regionGrabbed(const QPixmap&)), this, SLOT(screenshotGrabbed(const QPixmap&)) ); } void BNPView::grabScreenshotGlobal() { grabScreenshot(true); } void BNPView::screenshotGrabbed(const QPixmap &pixmap) { delete m_regionGrabber; m_regionGrabber = 0; // Cancelled (pressed Escape): if (pixmap.isNull()) { if (m_colorPickWasShown) showMainWindow(); return; } if (!currentBasket()->isLoaded()) { showPassiveLoading(currentBasket()); currentBasket()->load(); } currentBasket()->insertImage(pixmap); if (m_colorPickWasShown) showMainWindow(); if (Settings::usePassivePopup()) showPassiveDropped(i18n("Grabbed screen zone to basket %1")); } Basket* BNPView::basketForFolderName(const QString &/*folderName*/) { /* QPtrList basketsList = listBaskets(); Basket *basket; for (basket = basketsList.first(); basket; basket = basketsList.next()) if (basket->folderName() == folderName) return basket; */ return 0; } void BNPView::setFiltering(bool filtering) { m_actShowFilter->setChecked(filtering); m_actResetFilter->setEnabled(filtering); } void BNPView::undo() { // TODO } void BNPView::redo() { // TODO } void BNPView::pasteToBasket(int /*index*/, QClipboard::Mode /*mode*/) { //TODO: REMOVE! //basketAt(index)->pasteNote(mode); } void BNPView::propBasket() { BasketPropertiesDialog dialog(currentBasket(), this); dialog.exec(); } void BNPView::delBasket() { // DecoratedBasket *decoBasket = currentDecoratedBasket(); Basket *basket = currentBasket(); #if 0 KDialogBase *dialog = new KDialogBase(this, /*name=*/0, /*modal=*/true, /*caption=*/i18n("Delete Basket"), KDialogBase::User1 | KDialogBase::User2 | KDialogBase::No, KDialogBase::User1, /*separator=*/false, /*user1=*/KGuiItem(i18n("Delete Only that Basket")/*, icon=""*/), /*user2=*/KGuiItem(i18n("Delete Note & Children")/*, icon=""*/) ); QStringList basketsList; basketsList.append("Basket 1"); basketsList.append(" Basket 2"); basketsList.append(" Basket 3"); basketsList.append(" Basket 4"); KMessageBox::createKMessageBox( dialog, QMessageBox::Information, i18n("Do you really want to remove the basket %1 and its contents?") .arg(Tools::textToHTMLWithoutP(basket->basketName())), basketsList, /*ask=*/"", /*checkboxReturn=*/0, /*options=*/KMessageBox::Notify/*, const QString &details=QString::null*/); #endif int really = KMessageBox::questionYesNo( this, i18n("Do you really want to remove the basket %1 and its contents?") .arg(Tools::textToHTMLWithoutP(basket->basketName())), i18n("Remove Basket") #if KDE_IS_VERSION( 3, 2, 90 ) // KDE 3.3.x , KGuiItem(i18n("&Remove Basket"), "editdelete"), KStdGuiItem::cancel()); #else ); #endif if (really == KMessageBox::No) return; QStringList basketsList = listViewItemForBasket(basket)->childNamesTree(); if (basketsList.count() > 0) { int deleteChilds = KMessageBox::questionYesNoList( this, i18n("%1 have the following children baskets.
Do you want to remove them too?
") .arg(Tools::textToHTMLWithoutP(basket->basketName())), basketsList, i18n("Remove Children Baskets") #if KDE_IS_VERSION( 3, 2, 90 ) // KDE 3.3.x , KGuiItem(i18n("&Remove Children Baskets"), "editdelete")); #else ); #endif if (deleteChilds == KMessageBox::No) listViewItemForBasket(basket)->moveChildsBaskets(); } doBasketDeletion(basket); // basketNumberChanged(); // rebuildBasketsMenu(); } void BNPView::doBasketDeletion(Basket *basket) { basket->closeEditor(); QListViewItem *basketItem = listViewItemForBasket(basket); QListViewItem *nextOne; for (QListViewItem *child = basketItem->firstChild(); child; child = nextOne) { nextOne = child->nextSibling(); // First delete the child baskets: doBasketDeletion(((BasketListViewItem*)child)->basket()); } // Then, basket have no child anymore, delete it: DecoratedBasket *decoBasket = basket->decoration(); basket->deleteFiles(); removeBasket(basket); // Remove the action to avoir keyboard-shortcut clashes: delete basket->m_action; // FIXME: It's quick&dirty. In the future, the Basket should be deleted, and then the KAction deleted in the Basket destructor. delete decoBasket; // delete basket; } void BNPView::password() { #ifdef HAVE_LIBGPGME PasswordDlg dlg(kapp->activeWindow(), "Password"); Basket *cur = currentBasket(); dlg.setType(cur->encryptionType()); dlg.setKey(cur->encryptionKey()); if(dlg.exec()) { cur->setProtection(dlg.type(), dlg.key()); if (cur->encryptionType() != Basket::NoEncryption) cur->lock(); } #endif } void BNPView::lockBasket() { #ifdef HAVE_LIBGPGME Basket *cur = currentBasket(); cur->lock(); #endif } void BNPView::saveAsArchive() { Basket *basket = currentBasket(); QDir dir; KConfig *config = KGlobal::config(); config->setGroup("Basket Archive"); QString folder = config->readEntry("lastFolder", QDir::homeDirPath()) + "/"; QString url = folder + QString(basket->basketName()).replace("/", "_") + ".baskets"; QString filter = "*.baskets|" + i18n("Basket Archives") + "\n*|" + i18n("All Files"); QString destination = url; for (bool askAgain = true; askAgain; ) { destination = KFileDialog::getSaveFileName(destination, filter, this, i18n("Save as Basket Archive")); if (destination.isEmpty()) // User canceled return; if (dir.exists(destination)) { int result = KMessageBox::questionYesNoCancel( this, "" + i18n("The file %1 already exists. Do you really want to override it?") .arg(KURL(destination).fileName()), i18n("Override File?"), KGuiItem(i18n("&Override"), "filesave") ); if (result == KMessageBox::Cancel) return; else if (result == KMessageBox::Yes) askAgain = false; } else askAgain = false; } bool withSubBaskets = true;//KMessageBox::questionYesNo(this, i18n("Do you want to export sub-baskets too?"), i18n("Save as Basket Archive")) == KMessageBox::Yes; config->writeEntry("lastFolder", KURL(destination).directory()); config->sync(); Archive::save(basket, withSubBaskets, destination); } QString BNPView::s_fileToOpen = ""; void BNPView::delayedOpenArchive() { Archive::open(s_fileToOpen); } void BNPView::openArchive() { QString filter = "*.baskets|" + i18n("Basket Archives") + "\n*|" + i18n("All Files"); QString path = KFileDialog::getOpenFileName(QString::null, filter, this, i18n("Open Basket Archive")); if (!path.isEmpty()) // User has not canceled Archive::open(path); } void BNPView::activatedTagShortcut() { Tag *tag = Tag::tagForKAction((KAction*)sender()); currentBasket()->activatedTagShortcut(tag); } void BNPView::slotBasketNumberChanged(int number) { m_actPreviousBasket->setEnabled(number > 1); m_actNextBasket ->setEnabled(number > 1); } void BNPView::slotBasketChanged() { m_actFoldBasket->setEnabled(canFold()); m_actExpandBasket->setEnabled(canExpand()); setFiltering(currentBasket() && currentBasket()->decoration()->filterData().isFiltering); } void BNPView::currentBasketChanged() { } void BNPView::isLockedChanged() { bool isLocked = currentBasket()->isLocked(); setLockStatus(isLocked); // m_actLockBasket->setChecked(isLocked); m_actPropBasket->setEnabled(!isLocked); m_actDelBasket ->setEnabled(!isLocked); updateNotesActions(); } void BNPView::askNewBasket() { askNewBasket(0, 0); } void BNPView::askNewBasket(Basket *parent, Basket *pickProperties) { NewBasketDefaultProperties properties; if (pickProperties) { properties.icon = pickProperties->icon(); properties.backgroundImage = pickProperties->backgroundImageName(); properties.backgroundColor = pickProperties->backgroundColorSetting(); properties.textColor = pickProperties->textColorSetting(); properties.freeLayout = pickProperties->isFreeLayout(); properties.columnCount = pickProperties->columnsCount(); } NewBasketDialog(parent, properties, this).exec(); } void BNPView::askNewSubBasket() { askNewBasket( /*parent=*/currentBasket(), /*pickPropertiesOf=*/currentBasket() ); } void BNPView::askNewSiblingBasket() { askNewBasket( /*parent=*/parentBasketOf(currentBasket()), /*pickPropertiesOf=*/currentBasket() ); } void BNPView::globalPasteInCurrentBasket() { currentBasket()->setInsertPopupMenu(); pasteInCurrentBasket(); currentBasket()->cancelInsertPopupMenu(); } void BNPView::pasteInCurrentBasket() { currentBasket()->pasteNote(); if (Settings::usePassivePopup()) showPassiveDropped(i18n("Clipboard content pasted to basket %1")); } void BNPView::pasteSelInCurrentBasket() { currentBasket()->pasteNote(QClipboard::Selection); if (Settings::usePassivePopup()) showPassiveDropped(i18n("Selection pasted to basket %1")); } void BNPView::showPassiveDropped(const QString &title) { if ( ! currentBasket()->isLocked() ) { // TODO: Keep basket, so that we show the message only if something was added to a NOT visible basket m_passiveDroppedTitle = title; m_passiveDroppedSelection = currentBasket()->selectedNotes(); QTimer::singleShot( c_delayTooltipTime, this, SLOT(showPassiveDroppedDelayed()) ); // DELAY IT BELOW: } else showPassiveImpossible(i18n("No note was added.")); } void BNPView::showPassiveDroppedDelayed() { if (isMainWindowActive() || m_passiveDroppedSelection == 0) return; QString title = m_passiveDroppedTitle; delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time) m_passivePopup = new KPassivePopup(Settings::useSystray() ? (QWidget*)Global::systemTray : this); QPixmap contentsPixmap = NoteDrag::feedbackPixmap(m_passiveDroppedSelection); QMimeSourceFactory::defaultFactory()->setPixmap("_passivepopup_image_", contentsPixmap); m_passivePopup->setView( title.arg(Tools::textToHTMLWithoutP(currentBasket()->basketName())), (contentsPixmap.isNull() ? "" : ""), kapp->iconLoader()->loadIcon(currentBasket()->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true)); m_passivePopup->show(); } void BNPView::showPassiveImpossible(const QString &message) { delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time) m_passivePopup = new KPassivePopup(Settings::useSystray() ? (QWidget*)Global::systemTray : (QWidget*)this); m_passivePopup->setView( QString("%1") .arg(i18n("Basket %1 is locked")) .arg(Tools::textToHTMLWithoutP(currentBasket()->basketName())), message, kapp->iconLoader()->loadIcon(currentBasket()->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true)); m_passivePopup->show(); } void BNPView::showPassiveContentForced() { showPassiveContent(/*forceShow=*/true); } void BNPView::showPassiveContent(bool forceShow/* = false*/) { if (!forceShow && isMainWindowActive()) return; // FIXME: Duplicate code (2 times) QString message; delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time) m_passivePopup = new KPassivePopup(Settings::useSystray() ? (QWidget*)Global::systemTray : (QWidget*)this); m_passivePopup->setView( "" + kapp->makeStdCaption( currentBasket()->isLocked() ? QString("%1 %2") .arg(Tools::textToHTMLWithoutP(currentBasket()->basketName()), i18n("(Locked)")) : Tools::textToHTMLWithoutP(currentBasket()->basketName()) ), message, kapp->iconLoader()->loadIcon(currentBasket()->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true)); m_passivePopup->show(); } void BNPView::showPassiveLoading(Basket *basket) { if (isMainWindowActive()) return; delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time) m_passivePopup = new KPassivePopup(Settings::useSystray() ? (QWidget*)Global::systemTray : (QWidget*)this); m_passivePopup->setView( Tools::textToHTMLWithoutP(basket->basketName()), i18n("Loading..."), kapp->iconLoader()->loadIcon(basket->icon(), KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true)); m_passivePopup->show(); } void BNPView::addNoteText() { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Text); } void BNPView::addNoteHtml() { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Html); } void BNPView::addNoteImage() { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Image); } void BNPView::addNoteLink() { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Link); } void BNPView::addNoteColor() { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Color); } void BNPView::aboutToHideNewBasketPopup() { QTimer::singleShot(0, this, SLOT(cancelNewBasketPopup())); } void BNPView::cancelNewBasketPopup() { m_newBasketPopup = false; } void BNPView::setNewBasketPopup() { m_newBasketPopup = true; } void BNPView::setCaption(QString s) { emit setWindowCaption(s); } void BNPView::updateStatusBarHint() { m_statusbar->updateStatusBarHint(); } void BNPView::setSelectionStatus(QString s) { m_statusbar->setSelectionStatus(s); } void BNPView::setLockStatus(bool isLocked) { m_statusbar->setLockStatus(isLocked); } void BNPView::postStatusbarMessage(const QString& msg) { m_statusbar->postStatusbarMessage(msg); } void BNPView::setStatusBarHint(const QString &hint) { m_statusbar->setStatusBarHint(hint); } void BNPView::setUnsavedStatus(bool isUnsaved) { m_statusbar->setUnsavedStatus(isUnsaved); } void BNPView::setActive(bool active) { // std::cout << "Main Window Position: setActive(" << (active ? "true" : "false") << ")" << std::endl; KMainWindow* win = Global::mainWindow(); if(!win) return; #if KDE_IS_VERSION( 3, 2, 90 ) // KDE 3.3.x if (active) { kapp->updateUserTimestamp(); // If "activate on mouse hovering systray", or "on drag throught systray" Global::systemTray->setActive(); // FIXME: add this in the places it need } else Global::systemTray->setInactive(); #elif KDE_IS_VERSION( 3, 1, 90 ) // KDE 3.2.x // Code from Kopete (that seem to work, in waiting KSystemTray make puplic the toggleSHown) : if (active) { win->show(); //raise() and show() should normaly deIconify the window. but it doesn't do here due // to a bug in Qt or in KDE (qt3.1.x or KDE 3.1.x) then, i have to call KWin's method if (win->isMinimized()) KWin::deIconifyWindow(winId()); if ( ! KWin::windowInfo(winId(), NET::WMDesktop).onAllDesktops() ) KWin::setOnDesktop(winId(), KWin::currentDesktop()); win->raise(); // Code from me: expected and correct behavviour: kapp->updateUserTimestamp(); // If "activate on mouse hovering systray", or "on drag throught systray" KWin::activateWindow(win->winId()); } else win->hide(); #else // KDE 3.1.x and lower if (win->active) { if (win->isMinimized()) win->hide(); // If minimized, show() doesn't work ! win->show(); // Show it // showNormal(); // If it was minimized win->raise(); // Raise it on top win->setActiveWindow(); // And set it the active window } else win->hide(); #endif } void BNPView::hideOnEscape() { if (Settings::useSystray()) setActive(false); } bool BNPView::isPart() { return (strcmp(name(), "BNPViewPart") == 0); } bool BNPView::isMainWindowActive() { KMainWindow* main = Global::mainWindow(); if (main && main->isActiveWindow()) return true; return false; } void BNPView::newBasket() { askNewBasket(); } void BNPView::handleCommandLine() { KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); /* Custom data folder */ QCString customDataFolder = args->getOption("data-folder"); if (customDataFolder != 0 && !customDataFolder.isEmpty()) { Global::setCustomSavesFolder(customDataFolder); } /* Debug window */ if (args->isSet("debug")) { new DebugWindow(); Global::debugWindow->show(); } /* Crash Handler to Mail Developers when Crashing: */ #ifndef BASKET_USE_DRKONQI if (!args->isSet("use-drkonquy")) KCrash::setCrashHandler(Crash::crashHandler); #endif } /** Scenario of "Hide main window to system tray icon when mouse move out of the window" : * - At enterEvent() we stop m_tryHideTimer * - After that and before next, we are SURE cursor is hovering window * - At leaveEvent() we restart m_tryHideTimer * - Every 'x' ms, timeoutTryHide() seek if cursor hover a widget of the application or not * - If yes, we musn't hide the window * - But if not, we start m_hideTimer to hide main window after a configured elapsed time * - timeoutTryHide() continue to be called and if cursor move again to one widget of the app, m_hideTimer is stopped * - If after the configured time cursor hasn't go back to a widget of the application, timeoutHide() is called * - It then hide the main window to systray icon * - When the user will show it, enterEvent() will be called the first time he enter mouse to it * - ... */ /** Why do as this ? Problems with the use of only enterEvent() and leaveEvent() : * - Resize window or hover titlebar isn't possible : leave/enterEvent * are * > Use the grip or Alt+rightDND to resize window * > Use Alt+DND to move window * - Each menu trigger the leavEvent */ void BNPView::enterEvent(QEvent*) { if(m_tryHideTimer) m_tryHideTimer->stop(); if(m_hideTimer) m_hideTimer->stop(); } void BNPView::leaveEvent(QEvent*) { if (Settings::useSystray() && Settings::hideOnMouseOut() && m_tryHideTimer) m_tryHideTimer->start(50); } void BNPView::timeoutTryHide() { // If a menu is displayed, do nothing for the moment if (kapp->activePopupWidget() != 0L) return; if (kapp->widgetAt(QCursor::pos()) != 0L) m_hideTimer->stop(); else if ( ! m_hideTimer->isActive() ) // Start only one time m_hideTimer->start(Settings::timeToHideOnMouseOut() * 100, true); // If a sub-dialog is oppened, we musn't hide the main window: if (kapp->activeWindow() != 0L && kapp->activeWindow() != Global::mainWindow()) m_hideTimer->stop(); } void BNPView::timeoutHide() { // We check that because the setting can have been set to off if (Settings::useSystray() && Settings::hideOnMouseOut()) setActive(false); m_tryHideTimer->stop(); } void BNPView::changedSelectedNotes() { // tabChanged(0); // FIXME: NOT OPTIMIZED } /*void BNPView::areSelectedNotesCheckedChanged(bool checked) { m_actCheckNotes->setChecked(checked && currentBasket()->showCheckBoxes()); }*/ void BNPView::enableActions() { Basket *basket = currentBasket(); if(!basket) return; if(m_actLockBasket) m_actLockBasket->setEnabled(!basket->isLocked() && basket->isEncrypted()); if(m_actPassBasket) m_actPassBasket->setEnabled(!basket->isLocked()); m_actPropBasket->setEnabled(!basket->isLocked()); m_actDelBasket->setEnabled(!basket->isLocked()); m_actExportToHtml->setEnabled(!basket->isLocked()); m_actShowFilter->setEnabled(!basket->isLocked()); m_actFilterAllBaskets->setEnabled(!basket->isLocked()); m_actResetFilter->setEnabled(!basket->isLocked()); basket->decoration()->filterBar()->setEnabled(!basket->isLocked()); } void BNPView::showMainWindow() { KMainWindow *win = Global::mainWindow(); if (win) { win->show(); } setActive(true); emit showPart(); } void BNPView::populateTagsMenu() { KPopupMenu *menu = (KPopupMenu*)(popupMenu("tags")); if (menu == 0 || currentBasket() == 0) // TODO: Display a messagebox. [menu is 0, surely because on first launch, the XMLGUI does not work!] return; menu->clear(); Note *referenceNote; if (currentBasket()->focusedNote() && currentBasket()->focusedNote()->isSelected()) referenceNote = currentBasket()->focusedNote(); else referenceNote = currentBasket()->firstSelected(); populateTagsMenu(*menu, referenceNote); m_lastOpenedTagsMenu = menu; // connect( menu, SIGNAL(aboutToHide()), this, SLOT(disconnectTagsMenu()) ); } void BNPView::populateTagsMenu(KPopupMenu &menu, Note *referenceNote) { if (currentBasket() == 0) return; currentBasket()->m_tagPopupNote = referenceNote; bool enable = currentBasket()->countSelecteds() > 0; QValueList::iterator it; Tag *currentTag; State *currentState; int i = 10; for (it = Tag::all.begin(); it != Tag::all.end(); ++it) { // Current tag and first state of it: currentTag = *it; currentState = currentTag->states().first(); QKeySequence sequence; if (!currentTag->shortcut().isNull()) sequence = currentTag->shortcut().operator QKeySequence(); menu.insertItem(StateMenuItem::checkBoxIconSet( (referenceNote ? referenceNote->hasTag(currentTag) : false), menu.colorGroup()), new StateMenuItem(currentState, sequence, true), i ); if (!currentTag->shortcut().isNull()) menu.setAccel(sequence, i); menu.setItemEnabled(i, enable); ++i; } menu.insertSeparator(); // menu.insertItem( /*SmallIconSet("editdelete"),*/ "&Assign new Tag...", 1 ); //id = menu.insertItem( SmallIconSet("editdelete"), "&Remove All", -2 ); //if (referenceNote->states().isEmpty()) // menu.setItemEnabled(id, false); // menu.insertItem( SmallIconSet("configure"), "&Customize...", 3 ); menu.insertItem( new IndentedMenuItem(i18n("&Assign new Tag...")), 1 ); menu.insertItem( new IndentedMenuItem(i18n("&Remove All"), "editdelete"), 2 ); menu.insertItem( new IndentedMenuItem(i18n("&Customize..."), "configure"), 3 ); menu.setItemEnabled(1, enable); if (!currentBasket()->selectedNotesHaveTags()) menu.setItemEnabled(2, false); connect( &menu, SIGNAL(activated(int)), currentBasket(), SLOT(toggledTagInMenu(int)) ); connect( &menu, SIGNAL(aboutToHide()), currentBasket(), SLOT(unlockHovering()) ); connect( &menu, SIGNAL(aboutToHide()), currentBasket(), SLOT(disableNextClick()) ); } void BNPView::connectTagsMenu() { connect( popupMenu("tags"), SIGNAL(aboutToShow()), this, SLOT(populateTagsMenu()) ); connect( popupMenu("tags"), SIGNAL(aboutToHide()), this, SLOT(disconnectTagsMenu()) ); } /* * The Tags menu is ONLY created once the BasKet KPart is first shown. * So we can use this menu only from then? * When the KPart is changed in Kontact, and then the BasKet KPart is shown again, * Kontact created a NEW Tags menu. So we should connect again. * But when Kontact main window is hidden and then re-shown, the menu does not change. * So we disconnect at hide event to ensure only one connection: the next show event will not connects another time. */ void BNPView::showEvent(QShowEvent*) { if (isPart()) QTimer::singleShot( 0, this, SLOT(connectTagsMenu()) ); if (m_firstShow) { m_firstShow = false; onFirstShow(); } if (isPart()/*TODO: && !LikeBack::enabledBar()*/) { Global::likeBack->enableBar(); } } void BNPView::hideEvent(QHideEvent*) { if (isPart()) { disconnect( popupMenu("tags"), SIGNAL(aboutToShow()), this, SLOT(populateTagsMenu()) ); disconnect( popupMenu("tags"), SIGNAL(aboutToHide()), this, SLOT(disconnectTagsMenu()) ); } if (isPart()) Global::likeBack->disableBar(); } void BNPView::disconnectTagsMenu() { QTimer::singleShot( 0, this, SLOT(disconnectTagsMenuDelayed()) ); } void BNPView::disconnectTagsMenuDelayed() { disconnect( m_lastOpenedTagsMenu, SIGNAL(activated(int)), currentBasket(), SLOT(toggledTagInMenu(int)) ); disconnect( m_lastOpenedTagsMenu, SIGNAL(aboutToHide()), currentBasket(), SLOT(unlockHovering()) ); disconnect( m_lastOpenedTagsMenu, SIGNAL(aboutToHide()), currentBasket(), SLOT(disableNextClick()) ); } void BNPView::showGlobalShortcutsSettingsDialog() { KKeyDialog::configure(Global::globalAccel); //.setCaption(..) Global::globalAccel->writeSettings(); } #include "bnpview.moc"