diff --git a/krusader/CMakeLists.txt b/krusader/CMakeLists.txt index 41b23866..0d2f8751 100644 --- a/krusader/CMakeLists.txt +++ b/krusader/CMakeLists.txt @@ -1,130 +1,131 @@ include_directories(${KF5_INCLUDES_DIRS} ${QT_INCLUDES}) configure_file(krusaderversion.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/krusaderversion.h) add_subdirectory(ActionMan) add_subdirectory(Archive) add_subdirectory(BookMan) add_subdirectory(Dialogs) add_subdirectory(DiskUsage) add_subdirectory(FileSystem) add_subdirectory(Filter) add_subdirectory(GUI) add_subdirectory(Konfigurator) add_subdirectory(KViewer) add_subdirectory(JobMan) add_subdirectory(Locate) add_subdirectory(MountMan) add_subdirectory(Panel) add_subdirectory(Search) add_subdirectory(Splitter) add_subdirectory(UserAction) if(SYNCHRONIZER_ENABLED) add_subdirectory(Synchronizer) endif(SYNCHRONIZER_ENABLED) message(STATUS "${CMAKE_CURRENT_SOURCE_DIR}: skipped subdir $(KRJSDIR)") set(krusader_SRCS krglobal.cpp actionsbase.cpp tabactions.cpp kractions.cpp paneltabbar.cpp panelmanager.cpp krservices.cpp main.cpp krusaderview.cpp krusader.cpp krslots.cpp kicons.cpp krdebuglogger.cpp ) file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*-apps-krusader_user.png") ecm_add_app_icon(krusader_SRCS ICONS ${ICONS_SRCS}) qt5_add_resources(krusader_RC_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc" ) add_executable(krusader ${krusader_SRCS} ${krusader_RC_SRCS}) target_link_libraries(krusader Panel + PanelView BookMan Dialogs DiskUsage GUI Konfigurator KViewer MountMan FileSystem Search Splitter Locate UserAction ActionMan KViewer Filter Dialogs GUI Archive JobMan KF5::Notifications KF5::Parts KF5::WindowSystem Qt5::PrintSupport Qt5::Concurrent ) if(SYNCHRONIZER_ENABLED) target_link_libraries( krusader Synchronizer ) endif(SYNCHRONIZER_ENABLED) install(TARGETS krusader ${INSTALL_TARGETS_DEFAULT_ARGS}) install(PROGRAMS org.kde.krusader.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) install(FILES krusaderui.rc krusaderlisterui.rc krviewer.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/krusader) install(FILES midnight_commander.color total_commander.color total_commander.keymap total_commander.keymap.info useraction_examples.xml layout.xml splash.png DESTINATION ${DATA_INSTALL_DIR}/krusader) install(FILES org.kde.krusader.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) ecm_install_icons(ICONS icons/16-apps-krusader_blue.png icons/16-apps-krusader_red.png icons/16-apps-krusader_root.png icons/16-apps-krusader_user.png icons/22-apps-krusader_blue.png icons/22-apps-krusader_red.png icons/22-apps-krusader_root.png icons/22-apps-krusader_shield.png icons/22-apps-krusader_user.png icons/32-apps-krusader_blue.png icons/32-apps-krusader_red.png icons/32-apps-krusader_root.png icons/32-apps-krusader_shield.png icons/32-apps-krusader_user.png icons/48-apps-krusader_blue.png icons/48-apps-krusader_red.png icons/48-apps-krusader_root.png icons/48-apps-krusader_shield.png icons/48-apps-krusader_user.png icons/64-apps-krusader_blue.png icons/64-apps-krusader_red.png icons/64-apps-krusader_root.png icons/64-apps-krusader_shield.png icons/64-apps-krusader_user.png icons/128-apps-krusader_root.png icons/128-apps-krusader_user.png DESTINATION ${ICON_INSTALL_DIR} ) diff --git a/krusader/GUI/terminaldock.cpp b/krusader/GUI/terminaldock.cpp index 6172f19c..fa565b1c 100644 --- a/krusader/GUI/terminaldock.cpp +++ b/krusader/GUI/terminaldock.cpp @@ -1,281 +1,281 @@ /***************************************************************************** * Copyright (C) 2008 Václav Juza * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "terminaldock.h" // QtCore #include #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include "kcmdline.h" #include "../kractions.h" #include "../krmainwindow.h" #include "../krservices.h" #include "../krslots.h" #include "../krusaderview.h" #include "../FileSystem/filesystem.h" -#include "../Panel/krview.h" +#include "../Panel/PanelView/krview.h" #include "../Panel/listpanel.h" #include "../Panel/listpanelactions.h" #include "../Panel/panelfunc.h" /** * A widget containing the konsolepart for the Embedded terminal emulator */ TerminalDock::TerminalDock(QWidget* parent, KrMainWindow *mainWindow) : QWidget(parent), _mainWindow(mainWindow), konsole_part(0), t(0), initialised(false) { terminal_hbox = new QHBoxLayout(this); } TerminalDock::~TerminalDock() { } bool TerminalDock::initialise() { if (! initialised) { // konsole part is not yet loaded or it has already failed KService::Ptr service = KService::serviceByDesktopName("konsolepart"); if (service) { QWidget *focusW = qApp->focusWidget(); // Create the part QString error; konsole_part = service->createInstance(this, this, QVariantList(), &error); if (konsole_part) { //loaded successfully terminal_hbox->addWidget(konsole_part->widget()); setFocusProxy(konsole_part->widget()); connect(konsole_part, SIGNAL(destroyed()), this, SLOT(killTerminalEmulator())); // must filter app events, because some of them are processed // by child widgets of konsole_part->widget() // and would not be received on konsole_part->widget() qApp->installEventFilter(this); t = qobject_cast(konsole_part); if (t) { lastPath = QDir::currentPath(); t->showShellInDir(lastPath); } initialised = true; } else KMessageBox::error(0, i18n("Cannot create embedded terminal.
" "The reported error was: %1", error)); // the Terminal Emulator may be hidden (if we are creating it only // to send command there and see the results later) if (focusW) { focusW->setFocus(); } else { ACTIVE_PANEL->gui->slotFocusOnMe(); } } else KMessageBox::sorry(0, i18nc("missing program - arg1 is a URL", "Cannot create embedded terminal.
" "You can fix this by installing Konsole:
%1", QString("%1").arg( "http://www.kde.org/applications/system/konsole")), 0, KMessageBox::AllowLink); } return isInitialised(); } void TerminalDock::killTerminalEmulator() { initialised = false; konsole_part = NULL; t = NULL; qApp->removeEventFilter(this); MAIN_VIEW->setTerminalEmulator(false); } void TerminalDock::sendInput(const QString& input, bool clearCommand) { if (!t) return; if (clearCommand) { // send SIGINT before input command to avoid unwanted behaviour when current line is not empty // and command is appended to current input (e.g. "rm -rf x " concatenated with 'cd /usr'); // code "borrowed" from Dolphin, Copyright (C) 2007-2010 by Peter Penz const int processId = t->terminalProcessId(); if (processId > 0) { kill(processId, SIGINT); } } t->sendInput(input); } /*! Sends a `cd` command to the embedded terminal emulator so as to synchronize the directory of the actual panel and the directory of the embedded terminal emulator. To avoid that Krusader's embedded terminal adds a lot of `cd` messages to the shell history: the user has to use bash and have set `HISTCONTROL=ignorespace` or `HISTCONTROL=ignoreboth` (which is the default in a lot of Linux distributions so in that case the user hasn't got to do anything), or the user has to use an equivalent method. */ void TerminalDock::sendCd(const QString& path) { if (path.compare(lastPath) != 0) { // A space exists in front of the `cd` so as to avoid that Krusader's embedded terminal adds a lot of `cd` // messages to the shell history, in Dolphin it's done the same way: https://bugs.kde.org/show_bug.cgi?id=204039 sendInput(QString(" cd ") + KrServices::quote(path) + QString("\n")); lastPath = path; } } bool TerminalDock::applyShortcuts(QKeyEvent * ke) { int pressedKey = (ke->key() | ke->modifiers()); // TODO KF5 removed if (KrActions::actToggleTerminal->shortcut().matches(pressedKey)) { KrActions::actToggleTerminal->activate(QAction::Trigger); return true; } if (!krSwitchFullScreenTE->shortcut().isEmpty() && krSwitchFullScreenTE->shortcut().matches(pressedKey)) { krSwitchFullScreenTE->activate(QAction::Trigger); return true; } if (_mainWindow->listPanelActions()->actPaste->shortcut().matches(pressedKey)) { QString text = QApplication::clipboard()->text(); if (! text.isEmpty()) { text.replace('\n', '\r'); sendInput(text, false); } return true; } //insert current to the terminal if ((ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return) && (ke->modifiers() & Qt::ControlModifier)) { SLOTS->insertFileName((ke->modifiers() & Qt::ShiftModifier) != 0); return true; } //navigation if ((ke->key() == Qt::Key_Down) && (ke->modifiers() == Qt::ControlModifier)) { if (MAIN_VIEW->cmdLine()->isVisible()) { MAIN_VIEW->cmdLine()->setFocus(); } return true; } else if ((ke->key() == Qt::Key_Up) && ((ke->modifiers() == Qt::ControlModifier) || (ke->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)))) { ACTIVE_PANEL->gui->slotFocusOnMe(); return true; } return false; } bool TerminalDock::eventFilter(QObject * watched, QEvent * e) { if (konsole_part == NULL || konsole_part->widget() == NULL) return false; // we must watch for child widgets as well, // otherwise some shortcuts are "eaten" by them before // being procesed in konsole_part->widget() context // examples are Ctrl+F, Ctrl+Enter QObject *w; for (w = watched; w != NULL; w = w->parent()) if (w == konsole_part->widget()) break; if (w == NULL) // is not a child of konsole_part return false; switch (e->type()) { case QEvent::ShortcutOverride: { QKeyEvent *ke = (QKeyEvent *)e; // If not present, some keys would be considered a shortcut, for example "a" if ((ke->key() == Qt::Key_Insert) && (ke->modifiers() == Qt::ShiftModifier)) { ke->accept(); return true; } if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier) && (ke->key() >= 32) && (ke->key() <= 127)) { ke->accept(); return true; } break; } case QEvent::KeyPress: { QKeyEvent *ke = (QKeyEvent *)e; if (applyShortcuts(ke)) { ke->accept(); return true; } break; } default: return false; } return false; } bool TerminalDock::isTerminalVisible() const { return isVisible() && konsole_part != NULL && konsole_part->widget() != NULL && konsole_part->widget()->isVisible(); } bool TerminalDock::isInitialised() const { return konsole_part != NULL && konsole_part->widget() != NULL; } void TerminalDock::hideEvent(QHideEvent * /*e*/) { // BUGFIX: when the terminal emulator is toggled on, first it is shown in minimum size // then QSplitter resizes it to the desired size. // this minimum resize scrolls up the content of the konsole widget // SOLUTION: // we hide the console widget while the resize ceremony happens, then reenable it if (konsole_part && konsole_part->widget()) konsole_part->widget()->hide(); // hide the widget to prevent from resize } void TerminalDock::showEvent(QShowEvent * /*e*/) { if (konsole_part && konsole_part->widget()) { // BUGFIX: TE scrolling bug (see upper) // show the Konsole part delayed QTimer::singleShot(0, konsole_part->widget(), SLOT(show())); } } diff --git a/krusader/Konfigurator/kgpanel.cpp b/krusader/Konfigurator/kgpanel.cpp index 43e08bae..af51b43d 100644 --- a/krusader/Konfigurator/kgpanel.cpp +++ b/krusader/Konfigurator/kgpanel.cpp @@ -1,747 +1,747 @@ /*************************************************************************** kgpanel.cpp - description ------------------- copyright : (C) 2003 by Csaba Karai copyright : (C) 2010 by Jan Lepper e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "kgpanel.h" #include "../defaults.h" #include "../Dialogs/krdialogs.h" // QtGui #include // QtWidgets #include #include #include #include #include #include #include #include "../GUI/krtreewidget.h" #include "../Panel/krsearchbar.h" -#include "../Panel/krselectionmode.h" -#include "../Panel/krview.h" -#include "../Panel/krviewfactory.h" +#include "../Panel/PanelView/krselectionmode.h" +#include "../Panel/PanelView/krview.h" +#include "../Panel/PanelView/krviewfactory.h" #include "../Panel/krlayoutfactory.h" enum { PAGE_GENERAL = 0, PAGE_VIEW, PAGE_PANELTOOLBAR, PAGE_MOUSE, PAGE_MEDIA_MENU, PAGE_LAYOUT }; KgPanel::KgPanel(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { tabWidget = new QTabWidget(this); setWidget(tabWidget); setWidgetResizable(true); setupGeneralTab(); setupPanelTab(); setupButtonsTab(); setupMouseModeTab(); setupMediaMenuTab(); setupLayoutTab(); } // --------------------------------------------------------------------------------------- // ---------------------------- General TAB ---------------------------------------------- // --------------------------------------------------------------------------------------- void KgPanel::setupGeneralTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("General")); QVBoxLayout *layout = new QVBoxLayout(tab); layout->setSpacing(6); layout->setContentsMargins(11, 11, 11, 11); // --------------------------------------------------------------------------------------- // ------------------------------- Navigator bar ------------------------------------- // --------------------------------------------------------------------------------------- QGroupBox *groupBox = createFrame(i18n("Navigator bar"), tab); QGridLayout *gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM navigatorbar_settings[] = { // cfg_class, cfg_name, default, text, restart, tooltip {"Look&Feel", "Navigator Edit Mode", false, i18n("Edit Mode by default"), true, i18n("Show editable path in Navigator bar by default") }, {"Look&Feel", "Navigator Full Path", false, i18n("Show full path by default"), true, i18n("Always show full path in Navigator bar by default.") }, }; cbs = createCheckBoxGroup(2, 0, navigatorbar_settings, 2 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(cbs, 0, 0); layout->addWidget(groupBox); // --------------------------------------------------------------------------------------- // ------------------------------- Operation --------------------------------------------- // --------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Operation"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM operation_settings[] = { // cfg_class, cfg_name, default, text, restart, tooltip {"Look&Feel", "Mark Dirs", _MarkDirs, i18n("Autoselect folders"), false, i18n("When matching the select criteria, not only files will be selected, but also folders.") }, {"Look&Feel", "Rename Selects Extension", true, i18n("Rename selects extension"), false, i18n("When renaming a file, the whole text is selected. If you want Total-Commander like renaming of just the name, without extension, uncheck this option.") }, {"Look&Feel", "UnselectBeforeOperation", _UnselectBeforeOperation, i18n("Unselect files before copy/move"), false, i18n("Unselect files, which are to be copied/moved, before the operation starts.") }, {"Look&Feel", "FilterDialogRemembersSettings", _FilterDialogRemembersSettings, i18n("Filter dialog remembers settings"), false, i18n("The filter dialog is opened with the last filter settings that where applied to the panel.") }, }; cbs = createCheckBoxGroup(2, 0, operation_settings, 4 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(cbs, 0, 0); layout->addWidget(groupBox); // --------------------------------------------------------------------------------------- // ------------------------------ Tabs --------------------------------------------------- // --------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Tabs"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM tabbar_settings[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Fullpath Tab Names", _FullPathTabNames, i18n("Use full path tab names"), true , i18n("Display the full path in the folder tabs. By default only the last part of the path is displayed.") }, {"Look&Feel", "Show Tab Buttons", true, i18n("Show new/close tab buttons"), true , i18n("Show the new/close tab buttons.") }, }; KonfiguratorCheckBoxGroup *cbs = createCheckBoxGroup(2, 0, tabbar_settings, 2 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(cbs, 0, 0, 1, 2); // ----------------- Tab Bar position ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Tab Bar position:"), groupBox)); KONFIGURATOR_NAME_VALUE_PAIR positions[] = { { i18n("Top"), "top" }, { i18n("Bottom"), "bottom" } }; KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Tab Bar Position", "bottom", positions, 2, groupBox, true, false, PAGE_GENERAL); hbox->addWidget(cmb); gridLayout->addLayout(hbox, 1, 0, Qt::AlignLeft); // ----------------- Show Tab bar ---------------------------------- KonfiguratorCheckBox *checkBox = createCheckBox("Look&Feel", "Show Tab Bar On Single Tab", true, i18n("Show Tab Bar on single tab"), groupBox, true, i18n("Show the tab bar with only one tab.")); gridLayout->addWidget(checkBox, 1, 1, Qt::AlignLeft); layout->addWidget(groupBox); // --------------------------------------------------------------------------------------- // ----------------------------- Search bar -------------------------------------------- // --------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Search bar"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM quicksearch[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "New Style Quicksearch", _NewStyleQuicksearch, i18n("Start by typing"), false, i18n("Open search bar and start searching by typing in panel.") }, {"Look&Feel", "Case Sensitive Quicksearch", _CaseSensitiveQuicksearch, i18n("Case sensitive"), false, i18n("Search must match case.") }, {"Look&Feel", "Up/Down Cancels Quicksearch", false, i18n("Up/Down cancels search"), false, i18n("Pressing the Up/Down buttons closes the search bar (only in search mode).") }, }; quicksearchCheckboxes = createCheckBoxGroup(2, 0, quicksearch, 3 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(quicksearchCheckboxes, 0, 0, 1, -1); connect(quicksearchCheckboxes->find("New Style Quicksearch"), SIGNAL(stateChanged(int)), this, SLOT(slotDisable())); slotDisable(); // -------------- Search bar position ----------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Position:"), groupBox)); cmb = createComboBox("Look&Feel", "Quicksearch Position", "bottom", positions, 2, groupBox, true, false, PAGE_GENERAL); hbox->addWidget(cmb); hbox->addWidget(createSpacer(groupBox)); gridLayout->addLayout(hbox, 1, 0); layout->addWidget(groupBox); // -------------- Default search mode ----------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default mode:"), groupBox)); KONFIGURATOR_NAME_VALUE_PAIR modes[] = { { i18n("Search"), QString::number(KrSearchBar::MODE_SEARCH) }, { i18n("Select"), QString::number(KrSearchBar::MODE_SELECT) }, { i18n("Filter"), QString::number(KrSearchBar::MODE_FILTER) } }; cmb = createComboBox("Look&Feel", "Default Search Mode", QString::number(KrSearchBar::MODE_SEARCH), modes, 3, groupBox, true, false, PAGE_GENERAL); cmb->setToolTip(i18n("Set the default mode on first usage")); hbox->addWidget(cmb); hbox->addWidget(createSpacer(groupBox)); gridLayout->addLayout(hbox, 1, 1); layout->addWidget(groupBox); // -------------------------------------------------------------------------------------------- // ------------------------------- Status/Totalsbar settings ---------------------------------- // -------------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Status/Totalsbar"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM barSettings[] = { {"Look&Feel", "Show Size In Bytes", false, i18n("Show size in bytes too"), true, i18n("Show size in bytes too") }, {"Look&Feel", "ShowSpaceInformation", true, i18n("Show space information"), true, i18n("Show free/total space on the device") }, }; KonfiguratorCheckBoxGroup *barSett = createCheckBoxGroup(2, 0, barSettings, 2 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(barSett, 1, 0, 1, 2); layout->addWidget(groupBox); } // -------------------------------------------------------------------------------------------- // ------------------------------------ Layout Tab -------------------------------------------- // -------------------------------------------------------------------------------------------- void KgPanel::setupLayoutTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Layout")); QGridLayout *grid = createGridLayout(tab); QStringList layoutNames = KrLayoutFactory::layoutNames(); int numLayouts = layoutNames.count(); grid->addWidget(createSpacer(tab), 0, 2); QLabel *l = new QLabel(i18n("Layout:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 0, 0); KONFIGURATOR_NAME_VALUE_PAIR *layouts = new KONFIGURATOR_NAME_VALUE_PAIR[numLayouts]; for (int i = 0; i != numLayouts; i++) { layouts[ i ].text = KrLayoutFactory::layoutDescription(layoutNames[i]); layouts[ i ].value = layoutNames[i]; } KonfiguratorComboBox *cmb = createComboBox("PanelLayout", "Layout", "default", layouts, numLayouts, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 0, 1); delete [] layouts; l = new QLabel(i18n("Frame Color:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 1, 0); KONFIGURATOR_NAME_VALUE_PAIR frameColor[] = { { i18nc("Frame color", "Defined by Layout"), "default" }, { i18nc("Frame color", "None"), "none" }, { i18nc("Frame color", "Statusbar"), "Statusbar" } }; cmb = createComboBox("PanelLayout", "FrameColor", "default", frameColor, 3, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 1, 1); l = new QLabel(i18n("Frame Shape:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 2, 0); KONFIGURATOR_NAME_VALUE_PAIR frameShape[] = { { i18nc("Frame shape", "Defined by Layout"), "default" }, { i18nc("Frame shape", "None"), "NoFrame" }, { i18nc("Frame shape", "Box"), "Box" }, { i18nc("Frame shape", "Panel"), "Panel" }, }; cmb = createComboBox("PanelLayout", "FrameShape", "default", frameShape, 4, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 2, 1); l = new QLabel(i18n("Frame Shadow:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 3, 0); KONFIGURATOR_NAME_VALUE_PAIR frameShadow[] = { { i18nc("Frame shadow", "Defined by Layout"), "default" }, { i18nc("Frame shadow", "None"), "Plain" }, { i18nc("Frame shadow", "Raised"), "Raised" }, { i18nc("Frame shadow", "Sunken"), "Sunken" }, }; cmb = createComboBox("PanelLayout", "FrameShadow", "default", frameShadow, 4, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 3, 1); } void KgPanel::setupView(KrViewInstance *instance, QWidget *parent) { QGridLayout *grid = createGridLayout(parent); // -------------------- Filelist icon size ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default icon size:"), parent)); KONFIGURATOR_NAME_VALUE_PAIR *iconSizes = new KONFIGURATOR_NAME_VALUE_PAIR[KrView::iconSizes.count()]; for(int i = 0; i < KrView::iconSizes.count(); i++) iconSizes[i].text = iconSizes[i].value = QString::number(KrView::iconSizes[i]); KonfiguratorComboBox *cmb = createComboBox(instance->name(), "IconSize", _FilelistIconSize, iconSizes, KrView::iconSizes.count(), parent, true, true, PAGE_VIEW); delete [] iconSizes; cmb->lineEdit()->setValidator(new QRegExpValidator(QRegExp("[1-9]\\d{0,1}"), cmb)); hbox->addWidget(cmb); hbox->addWidget(createSpacer(parent)); grid->addLayout(hbox, 1, 0); //-------------------------------------------------------------------- KONFIGURATOR_CHECKBOX_PARAM iconSettings[] = // cfg_class cfg_name default text restart tooltip { {instance->name(), "With Icons", _WithIcons, i18n("Use icons in the filenames"), true, i18n("Show the icons for filenames and folders.") }, {instance->name(), "ShowPreviews", false, i18n("Show previews by default"), false, i18n("Show previews of files and folders.") }, }; KonfiguratorCheckBoxGroup *iconSett = createCheckBoxGroup(2, 0, iconSettings, 2 /*count*/, parent, PAGE_VIEW); grid->addWidget(iconSett, 2, 0, 1, 2); } // ---------------------------------------------------------------------------------- // ---------------------------- VIEW TAB ------------------------------------------- // ---------------------------------------------------------------------------------- void KgPanel::setupPanelTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab_panel = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab_panel); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("View")); QGridLayout *panelLayout = new QGridLayout(tab_panel); panelLayout->setSpacing(6); panelLayout->setContentsMargins(11, 11, 11, 11); QGroupBox *panelGrp = createFrame(i18n("General"), tab_panel); panelLayout->addWidget(panelGrp, 0, 0); QGridLayout *panelGrid = createGridLayout(panelGrp); // ---------------------------------------------------------------------------------- // ---------------------------- General settings ----------------------------------- // ---------------------------------------------------------------------------------- // -------------------- Panel Font ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); QHBoxLayout *fontLayout = new QHBoxLayout(); fontLayout->addWidget(new QLabel(i18n("View font:"), panelGrp)); KonfiguratorFontChooser *chsr = createFontChooser("Look&Feel", "Filelist Font", _FilelistFont, panelGrp, true, PAGE_VIEW); fontLayout->addWidget(chsr); fontLayout->addStretch(1); hbox->addLayout(fontLayout, 1); // -------------------- Panel Tooltip ---------------------------------- QHBoxLayout *tooltipLayout = new QHBoxLayout(); QLabel *tooltipLabel = new QLabel(i18n("Tooltip delay (msec):")); tooltipLabel->setWhatsThis(i18n("The duration after a tooltip is shown for a file item, in " "milliseconds. Set a negative value to disable tooltips.")); tooltipLayout->addWidget(tooltipLabel); KonfiguratorSpinBox *tooltipSpinBox = createSpinBox("Look&Feel", "Panel Tooltip Delay", 1000, -100, 5000, panelGrp, false, PAGE_VIEW); tooltipSpinBox->setSingleStep(100); tooltipLayout->addWidget(tooltipSpinBox); tooltipLayout->addStretch(1); hbox->addLayout(tooltipLayout, 1); panelGrid->addLayout(hbox, 1, 0); // -------------------- General options ---------------------------------- KONFIGURATOR_CHECKBOX_PARAM panelSettings[] = // cfg_class cfg_name default text restart tooltip { {"Look&Feel", "Human Readable Size", _HumanReadableSize, i18n("Use human-readable file size"), true , i18n("File sizes are displayed in B, KB, MB and GB, not just in bytes.") }, {"Look&Feel", "Show Hidden", _ShowHidden, i18n("Show hidden files"), false, i18n("Display files beginning with a dot.") }, {"Look&Feel", "Numeric permissions", _NumericPermissions, i18n("Numeric Permissions"), true, i18n("Show octal numbers (0755) instead of the standard permissions (rwxr-xr-x) in the permission column.") }, {"Look&Feel", "Load User Defined Folder Icons", _UserDefinedFolderIcons, i18n("Load the user defined folder icons"), true , i18n("Load the user defined folder icons (can cause decrease in performance).") }, {"Look&Feel", "Always Show Current Item", _AlwaysShowCurrentItem, i18n("Always show current item"), false, i18n("Show current item border decoration in inactive panel.") }, }; KonfiguratorCheckBoxGroup *panelSett = createCheckBoxGroup(2, 0, panelSettings, 5 /*count*/, panelGrp, PAGE_VIEW); panelGrid->addWidget(panelSett, 3, 0, 1, 2); // ========================================================= panelGrid->addWidget(createLine(panelGrp), 4, 0); // ------------------------ Sort Method ---------------------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Sort method:"), panelGrp)); KONFIGURATOR_NAME_VALUE_PAIR sortMethods[] = {{ i18n("Alphabetical"), QString::number(KrViewProperties::Alphabetical) }, { i18n("Alphabetical and numbers"), QString::number(KrViewProperties::AlphabeticalNumbers) }, { i18n("Character code"), QString::number(KrViewProperties::CharacterCode) }, { i18n("Character code and numbers"), QString::number(KrViewProperties::CharacterCodeNumbers) }, { i18nc("Krusader sort", "Krusader"), QString::number(KrViewProperties::Krusader) } }; KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Sort method", QString::number(_DefaultSortMethod), sortMethods, 5, panelGrp, true, false, PAGE_VIEW); hbox->addWidget(cmb); hbox->addWidget(createSpacer(panelGrp)); panelGrid->addLayout(hbox, 5, 0); // ------------------------ Sort Options ---------------------------------- KONFIGURATOR_CHECKBOX_PARAM sortSettings[] = // cfg_class, cfg_name, default, text, restart, tooltip { {"Look&Feel", "Case Sensative Sort", _CaseSensativeSort, i18n("Case sensitive sorting"), true, i18n("All files beginning with capital letters appear before files beginning with non-capital letters (UNIX default).") }, {"Look&Feel", "Show Directories First", true, i18n("Show folders first"), true, 0 }, {"Look&Feel", "Always sort dirs by name", false, i18n("Always sort dirs by name"), true, i18n("Folders are sorted by name, regardless of the sort column.") }, {"Look&Feel", "Locale Aware Sort", true, i18n("Locale aware sorting"), true, i18n("The sorting is performed in a locale- and also platform-dependent manner. Can be slow.") }, }; KonfiguratorCheckBoxGroup *sortSett = createCheckBoxGroup(2, 0, sortSettings, 4 /*count*/, panelGrp, PAGE_VIEW); sortSett->find("Show Directories First")->addDep(sortSett->find("Always sort dirs by name")); panelGrid->addWidget(sortSett, 6, 0, 1, 2); // ---------------------------------------------------------------------------------- // ---------------------------- View modes ----------------------------------------- // ---------------------------------------------------------------------------------- panelGrp = createFrame(i18n("View modes"), tab_panel); panelLayout->addWidget(panelGrp, 1, 0); panelGrid = createGridLayout(panelGrp); // -------------------- Default Panel Type ---------------------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default view mode:"), panelGrp)); QList views = KrViewFactory::registeredViews(); const int viewsSize = views.size(); KONFIGURATOR_NAME_VALUE_PAIR *panelTypes = new KONFIGURATOR_NAME_VALUE_PAIR[ viewsSize ]; QString defType = QString('0'); for (int i = 0; i != viewsSize; i++) { KrViewInstance * inst = views[ i ]; panelTypes[ i ].text = inst->description(); panelTypes[ i ].text.remove('&'); panelTypes[ i ].value = QString("%1").arg(inst->id()); if (inst->id() == KrViewFactory::defaultViewId()) defType = QString("%1").arg(inst->id()); } cmb = createComboBox("Look&Feel", "Default Panel Type", defType, panelTypes, viewsSize, panelGrp, false, false, PAGE_VIEW); hbox->addWidget(cmb); hbox->addWidget(createSpacer(panelGrp)); delete [] panelTypes; panelGrid->addLayout(hbox, 0, 0); // ----- Individual Settings Per View Type ------------------------ QTabWidget *tabs_view = new QTabWidget(panelGrp); panelGrid->addWidget(tabs_view, 11, 0); for(int i = 0; i < views.count(); i++) { QWidget *tab = new QWidget(tabs_view); tabs_view->addTab(tab, views[i]->description()); setupView(views[i], tab); } } // ----------------------------------------------------------------------------------- // -------------------------- Panel Toolbar TAB ---------------------------------- // ----------------------------------------------------------------------------------- void KgPanel::setupButtonsTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Buttons")); QBoxLayout * tabLayout = new QVBoxLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); KONFIGURATOR_CHECKBOX_PARAM buttonsParams[] = // cfg_class cfg_name default text restart tooltip { {"ListPanelButtons", "Icons", false, i18n("Toolbar buttons have icons"), true, "" }, {"Look&Feel", "Media Button Visible", true, i18n("Show Media Button"), true , i18n("The media button will be visible.") }, {"Look&Feel", "Back Button Visible", false, i18n("Show Back Button"), true , "Goes back in history." }, {"Look&Feel", "Forward Button Visible", false, i18n("Show Forward Button"), true , "Goes forward in history." }, {"Look&Feel", "History Button Visible", true, i18n("Show History Button"), true , i18n("The history button will be visible.") }, {"Look&Feel", "Bookmarks Button Visible", true, i18n("Show Bookmarks Button"), true , i18n("The bookmarks button will be visible.") }, {"Look&Feel", "Panel Toolbar visible", _PanelToolBar, i18n("Show Panel Toolbar"), true, i18n("The panel toolbar will be visible.") }, }; buttonsCheckboxes = createCheckBoxGroup(1, 0, buttonsParams, 7/*count*/, tab, PAGE_PANELTOOLBAR); connect(buttonsCheckboxes->find("Panel Toolbar visible"), SIGNAL(stateChanged(int)), this, SLOT(slotEnablePanelToolbar())); tabLayout->addWidget(buttonsCheckboxes, 0, 0); QGroupBox * panelToolbarGrp = createFrame(i18n("Visible Panel Toolbar buttons"), tab); QGridLayout * panelToolbarGrid = createGridLayout(panelToolbarGrp); KONFIGURATOR_CHECKBOX_PARAM panelToolbarButtonsParams[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Equal Button Visible", _cdOther, i18n("Equal button (=)"), true , i18n("Changes the panel folder to the other panel folder.") }, {"Look&Feel", "Up Button Visible", _cdUp, i18n("Up button (..)"), true , i18n("Changes the panel folder to the parent folder.") }, {"Look&Feel", "Home Button Visible", _cdHome, i18n("Home button (~)"), true , i18n("Changes the panel folder to the home folder.") }, {"Look&Feel", "Root Button Visible", _cdRoot, i18n("Root button (/)"), true , i18n("Changes the panel folder to the root folder.") }, {"Look&Feel", "SyncBrowse Button Visible", _syncBrowseButton, i18n("Toggle-button for sync-browsing"), true , i18n("Each folder change in the panel is also performed in the other panel.") }, }; panelToolbarButtonsCheckboxes = createCheckBoxGroup(1, 0, panelToolbarButtonsParams, sizeof(panelToolbarButtonsParams) / sizeof(*panelToolbarButtonsParams), panelToolbarGrp, PAGE_PANELTOOLBAR); panelToolbarGrid->addWidget(panelToolbarButtonsCheckboxes, 0, 0); tabLayout->addWidget(panelToolbarGrp, 1, 0); // Enable panel toolbar checkboxes slotEnablePanelToolbar(); } // --------------------------------------------------------------------------- // -------------------------- Mouse TAB ---------------------------------- // --------------------------------------------------------------------------- void KgPanel::setupMouseModeTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab_mouse = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab_mouse); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Selection Mode")); QGridLayout *mouseLayout = new QGridLayout(tab_mouse); mouseLayout->setSpacing(6); mouseLayout->setContentsMargins(11, 11, 11, 11); // -------------- General ----------------- QGroupBox *mouseGeneralGroup = createFrame(i18n("General"), tab_mouse); QGridLayout *mouseGeneralGrid = createGridLayout(mouseGeneralGroup); mouseGeneralGrid->setSpacing(0); mouseGeneralGrid->setContentsMargins(5, 5, 5, 5); KONFIGURATOR_NAME_VALUE_TIP mouseSelection[] = { // name value tooltip { i18n("Krusader Mode"), "0", i18n("Both keys allow selecting files. To select more than one file, hold the Ctrl key and click the left mouse button. Right-click menu is invoked using a short click on the right mouse button.") }, { i18n("Konqueror Mode"), "1", i18n("Pressing the left mouse button selects files - you can click and select multiple files. Right-click menu is invoked using a short click on the right mouse button.") }, { i18n("Total-Commander Mode"), "2", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button selects multiple files and the right-click menu is invoked by pressing and holding the right mouse button.") }, { i18n("Ergonomic Mode"), "4", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button invokes the context-menu. You can select with Ctrl key and the left button.") }, { i18n("Custom Selection Mode"), "3", i18n("Design your own selection mode.") } }; mouseRadio = createRadioButtonGroup("Look&Feel", "Mouse Selection", "0", 1, 5, mouseSelection, 5, mouseGeneralGroup, true, PAGE_MOUSE); mouseRadio->layout()->setContentsMargins(0, 0, 0, 0); mouseGeneralGrid->addWidget(mouseRadio, 0, 0); for (int i = 0; i != mouseRadio->count(); i++) connect(mouseRadio->find(i), SIGNAL(clicked()), SLOT(slotSelectionModeChanged())); mouseLayout->addWidget(mouseGeneralGroup, 0, 0); // -------------- Details ----------------- QGroupBox *mouseDetailGroup = createFrame(i18n("Details"), tab_mouse); QGridLayout *mouseDetailGrid = createGridLayout(mouseDetailGroup); mouseDetailGrid->setSpacing(0); mouseDetailGrid->setContentsMargins(5, 5, 5, 5); KONFIGURATOR_NAME_VALUE_TIP singleOrDoubleClick[] = { // name value tooltip { i18n("Double-click selects (classic)"), "0", i18n("A single click on a file will select and focus, a double click opens the file or steps into the folder.") }, { i18n("Obey global selection policy"), "1", i18n("

Use global setting:

Plasma System Settings -> Input Devices -> Mouse

") } }; KonfiguratorRadioButtons *clickRadio = createRadioButtonGroup("Look&Feel", "Single Click Selects", "0", 1, 0, singleOrDoubleClick, 2, mouseDetailGroup, true, PAGE_MOUSE); clickRadio->layout()->setContentsMargins(0, 0, 0, 0); mouseDetailGrid->addWidget(clickRadio, 0, 0); KONFIGURATOR_CHECKBOX_PARAM mouseCheckboxesParam[] = { // {cfg_class, cfg_name, default // text, restart, // tooltip } {"Custom Selection Mode", "QT Selection", _QtSelection, i18n("Based on KDE's selection mode"), true, i18n("If checked, use a mode based on KDE's style.") }, {"Custom Selection Mode", "Left Selects", _LeftSelects, i18n("Left mouse button selects"), true, i18n("If checked, left clicking an item will select it.") }, {"Custom Selection Mode", "Left Preserves", _LeftPreserves, i18n("Left mouse button preserves selection"), true, i18n("If checked, left clicking an item will select it, but will not unselect other, already selected items.") }, {"Custom Selection Mode", "ShiftCtrl Left Selects", _ShiftCtrlLeft, i18n("Shift/Ctrl-Left mouse button selects"), true, i18n("If checked, Shift/Ctrl left clicking will select items.\nNote: this is meaningless if 'Left Button Selects' is checked.") }, {"Custom Selection Mode", "Right Selects", _RightSelects, i18n("Right mouse button selects"), true, i18n("If checked, right clicking an item will select it.") }, {"Custom Selection Mode", "Right Preserves", _RightPreserves, i18n("Right mouse button preserves selection"), true, i18n("If checked, right clicking an item will select it, but will not unselect other, already selected items.") }, {"Custom Selection Mode", "ShiftCtrl Right Selects", _ShiftCtrlRight, i18n("Shift/Ctrl-Right mouse button selects"), true, i18n("If checked, Shift/Ctrl right clicking will select items.\nNote: this is meaningless if 'Right Button Selects' is checked.") }, {"Custom Selection Mode", "Space Moves Down", _SpaceMovesDown, i18n("Spacebar moves down"), true, i18n("If checked, pressing the spacebar will select the current item and move down.\nOtherwise, current item is selected, but remains the current item.") }, {"Custom Selection Mode", "Space Calc Space", _SpaceCalcSpace, i18n("Spacebar calculates disk space"), true, i18n("If checked, pressing the spacebar while the current item is a folder, will (except from selecting the folder)\ncalculate space occupied of the folder (recursively).") }, {"Custom Selection Mode", "Insert Moves Down", _InsertMovesDown, i18n("Insert moves down"), true, i18n("If checked, pressing Insert will select the current item, and move down to the next item.\nOtherwise, current item is not changed.") }, {"Custom Selection Mode", "Immediate Context Menu", _ImmediateContextMenu, i18n("Right clicking pops context menu immediately"), true, i18n("If checked, right clicking will result in an immediate showing of the context menu.\nOtherwise, user needs to click and hold the right mouse button for 500ms.") }, }; mouseCheckboxes = createCheckBoxGroup(1, 0, mouseCheckboxesParam, 11 /*count*/, mouseDetailGroup, PAGE_MOUSE); mouseDetailGrid->addWidget(mouseCheckboxes, 1, 0); for (int i = 0; i < mouseCheckboxes->count(); i++) connect(mouseCheckboxes->find(i), SIGNAL(clicked()), SLOT(slotMouseCheckBoxChanged())); mouseLayout->addWidget(mouseDetailGroup, 0, 1, 2, 1); // Disable the details-button if not in custom-mode slotSelectionModeChanged(); // -------------- Preview ----------------- QGroupBox *mousePreviewGroup = createFrame(i18n("Preview"), tab_mouse); QGridLayout *mousePreviewGrid = createGridLayout(mousePreviewGroup); // TODO preview mousePreview = new KrTreeWidget(mousePreviewGroup); mousePreviewGrid->addWidget(mousePreview, 0 , 0); mousePreviewGroup->setEnabled(false); // TODO re-enable once the preview is implemented // ------------------------------------------ mouseLayout->addWidget(mousePreviewGroup, 1, 0); } // --------------------------------------------------------------------------- // -------------------------- Media Menu TAB ---------------------------------- // --------------------------------------------------------------------------- void KgPanel::setupMediaMenuTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Media Menu")); QBoxLayout * tabLayout = new QVBoxLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); KONFIGURATOR_CHECKBOX_PARAM mediaMenuParams[] = { // cfg_class cfg_name default text restart tooltip {"MediaMenu", "ShowPath", true, i18n("Show Mount Path"), false, 0 }, {"MediaMenu", "ShowFSType", true, i18n("Show File System Type"), false, 0 }, }; KonfiguratorCheckBoxGroup *mediaMenuCheckBoxes = createCheckBoxGroup(1, 0, mediaMenuParams, sizeof(mediaMenuParams) / sizeof(*mediaMenuParams), tab, PAGE_MEDIA_MENU); tabLayout->addWidget(mediaMenuCheckBoxes, 0, 0); QHBoxLayout *showSizeHBox = new QHBoxLayout(); showSizeHBox->addWidget(new QLabel(i18n("Show Size:"), tab)); KONFIGURATOR_NAME_VALUE_PAIR showSizeValues[] = { { i18nc("setting 'show size'", "Always"), "Always" }, { i18nc("setting 'show size'", "When Device has no Label"), "WhenNoLabel" }, { i18nc("setting 'show size'", "Never"), "Never" }, }; KonfiguratorComboBox *showSizeCmb = createComboBox("MediaMenu", "ShowSize", "Always", showSizeValues, sizeof(showSizeValues) / sizeof(*showSizeValues), tab, false, false, PAGE_MEDIA_MENU); showSizeHBox->addWidget(showSizeCmb); showSizeHBox->addStretch(); tabLayout->addLayout(showSizeHBox); tabLayout->addStretch(); } void KgPanel::slotDisable() { bool isNewStyleQuickSearch = quicksearchCheckboxes->find("New Style Quicksearch")->isChecked(); quicksearchCheckboxes->find("Case Sensitive Quicksearch")->setEnabled(isNewStyleQuickSearch); } void KgPanel::slotEnablePanelToolbar() { bool enableTB = buttonsCheckboxes->find("Panel Toolbar visible")->isChecked(); panelToolbarButtonsCheckboxes->find("Root Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Home Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Up Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Equal Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("SyncBrowse Button Visible")->setEnabled(enableTB); } void KgPanel::slotSelectionModeChanged() { KrSelectionMode *selectionMode = KrSelectionMode::getSelectionHandlerForMode(mouseRadio->selectedValue()); if (selectionMode == NULL) //User mode return; selectionMode->init(); mouseCheckboxes->find("QT Selection")->setChecked(selectionMode->useQTSelection()); mouseCheckboxes->find("Left Selects")->setChecked(selectionMode->leftButtonSelects()); mouseCheckboxes->find("Left Preserves")->setChecked(selectionMode->leftButtonPreservesSelection()); mouseCheckboxes->find("ShiftCtrl Left Selects")->setChecked(selectionMode->shiftCtrlLeftButtonSelects()); mouseCheckboxes->find("Right Selects")->setChecked(selectionMode->rightButtonSelects()); mouseCheckboxes->find("Right Preserves")->setChecked(selectionMode->rightButtonPreservesSelection()); mouseCheckboxes->find("ShiftCtrl Right Selects")->setChecked(selectionMode->shiftCtrlRightButtonSelects()); mouseCheckboxes->find("Space Moves Down")->setChecked(selectionMode->spaceMovesDown()); mouseCheckboxes->find("Space Calc Space")->setChecked(selectionMode->spaceCalculatesDiskSpace()); mouseCheckboxes->find("Insert Moves Down")->setChecked(selectionMode->insertMovesDown()); mouseCheckboxes->find("Immediate Context Menu")->setChecked(selectionMode->showContextMenu() == -1); } void KgPanel::slotMouseCheckBoxChanged() { mouseRadio->selectButton("3"); //custom selection mode } int KgPanel::activeSubPage() { return tabWidget->currentIndex(); } diff --git a/krusader/Panel/CMakeLists.txt b/krusader/Panel/CMakeLists.txt index c41df584..0545d096 100644 --- a/krusader/Panel/CMakeLists.txt +++ b/krusader/Panel/CMakeLists.txt @@ -1,51 +1,42 @@ include_directories(${KF5_INCLUDES_DIRS} ${QT_INCLUDES}) +add_subdirectory(PanelView) + set(Panel_SRCS - viewactions.cpp - listpanelactions.cpp dirhistoryqueue.cpp - krsort.cpp - krlayoutfactory.cpp - krerrordisplay.cpp - krpreviews.cpp - krpreviewjob.cpp - krcolorcache.cpp krcalcspacedialog.cpp + krcolorcache.cpp + krerrordisplay.cpp + krfiletreeview.cpp + krlayoutfactory.cpp + krpanel.cpp krpopupmenu.cpp + krpreviewjob.cpp krpreviewpopup.cpp - krview.cpp - krviewproperties.cpp - krviewitem.cpp - panelfunc.cpp - krpanel.cpp + krpreviews.cpp + krsearchbar.cpp listpanel.cpp + listpanelactions.cpp listpanelframe.cpp + panelfunc.cpp panelpopup.cpp - krselectionmode.cpp - listmodel.cpp - krinterview.cpp - krinterbriefview.cpp - krinterdetailedview.cpp - krviewfactory.cpp - krviewitemdelegate.cpp - krmousehandler.cpp - krsearchbar.cpp - krfiletreeview.cpp) + viewactions.cpp +) add_library(Panel STATIC ${Panel_SRCS}) target_link_libraries(Panel Dialogs GUI KViewer KF5::Archive KF5::ConfigCore KF5::CoreAddons KF5::I18n KF5::IconThemes KF5::KIOFileWidgets KF5::KIOWidgets KF5::Service KF5::WidgetsAddons KF5::XmlGui ) diff --git a/krusader/Panel/CMakeLists.txt b/krusader/Panel/PanelView/CMakeLists.txt similarity index 53% copy from krusader/Panel/CMakeLists.txt copy to krusader/Panel/PanelView/CMakeLists.txt index c41df584..f2fc5414 100644 --- a/krusader/Panel/CMakeLists.txt +++ b/krusader/Panel/PanelView/CMakeLists.txt @@ -1,51 +1,34 @@ include_directories(${KF5_INCLUDES_DIRS} ${QT_INCLUDES}) -set(Panel_SRCS - viewactions.cpp - listpanelactions.cpp - dirhistoryqueue.cpp - krsort.cpp - krlayoutfactory.cpp - krerrordisplay.cpp - krpreviews.cpp - krpreviewjob.cpp - krcolorcache.cpp - krcalcspacedialog.cpp - krpopupmenu.cpp - krpreviewpopup.cpp - krview.cpp - krviewproperties.cpp - krviewitem.cpp - panelfunc.cpp - krpanel.cpp - listpanel.cpp - listpanelframe.cpp - panelpopup.cpp - krselectionmode.cpp - listmodel.cpp - krinterview.cpp +set(PanelView_SRCS krinterbriefview.cpp krinterdetailedview.cpp + krinterview.cpp + krmousehandler.cpp + krselectionmode.cpp + krsort.cpp + krview.cpp krviewfactory.cpp + krviewitem.cpp krviewitemdelegate.cpp - krmousehandler.cpp - krsearchbar.cpp - krfiletreeview.cpp) + krviewproperties.cpp + listmodel.cpp +) -add_library(Panel STATIC ${Panel_SRCS}) +add_library(PanelView STATIC ${PanelView_SRCS}) -target_link_libraries(Panel +target_link_libraries(PanelView Dialogs GUI KViewer KF5::Archive KF5::ConfigCore KF5::CoreAddons KF5::I18n KF5::IconThemes KF5::KIOFileWidgets KF5::KIOWidgets KF5::Service KF5::WidgetsAddons KF5::XmlGui ) diff --git a/krusader/Panel/krinterbriefview.cpp b/krusader/Panel/PanelView/krinterbriefview.cpp similarity index 99% rename from krusader/Panel/krinterbriefview.cpp rename to krusader/Panel/PanelView/krinterbriefview.cpp index 9b387060..93891301 100644 --- a/krusader/Panel/krinterbriefview.cpp +++ b/krusader/Panel/PanelView/krinterbriefview.cpp @@ -1,700 +1,700 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krinterbriefview.h" // QtCore #include #include #include #include // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include #include +#include "krmousehandler.h" #include "krviewfactory.h" #include "krviewitemdelegate.h" #include "krviewitem.h" #include "listmodel.h" -#include "krmousehandler.h" -#include "krcolorcache.h" +#include "../krcolorcache.h" #include "../FileSystem/krpermhandler.h" #include "../defaults.h" #include "../GUI/krstyleproxy.h" KrInterBriefView::KrInterBriefView(QWidget *parent, KrViewInstance &instance, KConfig *cfg) : QAbstractItemView(parent), KrInterView(instance, cfg, this), _header(0) { setWidget(this); setModel(_model); setSelectionMode(QAbstractItemView::NoSelection); setSelectionModel(new DummySelectionModel(_model, this)); KConfigGroup grpSvr(_config, "Look&Feel"); _viewFont = grpSvr.readEntry("Filelist Font", _FilelistFont); KrStyleProxy *style = new KrStyleProxy(); style->setParent(this); setStyle(style); viewport()->setStyle(style); // for custom tooltip delay setItemDelegate(new KrViewItemDelegate()); setMouseTracking(true); setAcceptDrops(true); setDropIndicatorShown(true); connect(_mouseHandler, SIGNAL(renameCurrentItem()), SLOT(renameCurrentItem())); _model->setExtensionEnabled(false); _model->setAlternatingTable(true); connect(_model, SIGNAL(layoutChanged()), SLOT(updateGeometries())); } KrInterBriefView::~KrInterBriefView() { delete _properties; _properties = 0; delete _operator; _operator = 0; } void KrInterBriefView::doRestoreSettings(KConfigGroup group) { _properties->numberOfColumns = group.readEntry("Number Of Brief Columns", _NumberOfBriefColumns); if (_properties->numberOfColumns < 1) _properties->numberOfColumns = 1; else if (_properties->numberOfColumns > MAX_BRIEF_COLS) _properties->numberOfColumns = MAX_BRIEF_COLS; _numOfColumns = _properties->numberOfColumns; KrInterView::doRestoreSettings(group); updateGeometries(); } void KrInterBriefView::saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) { KrInterView::saveSettings(grp, properties); if(properties & KrViewProperties::PropColumns) grp.writeEntry("Number Of Brief Columns", _numOfColumns); } int KrInterBriefView::itemsPerPage() { int height = getItemHeight(); if (height == 0) height ++; int numRows = viewport()->height() / height; return numRows; } void KrInterBriefView::updateView() { } void KrInterBriefView::setup() { _header = new QHeaderView(Qt::Horizontal, this); _header->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter); _header->setParent(this); _header->setModel(_model); _header->hideSection(KrViewProperties::Type); _header->hideSection(KrViewProperties::Permissions); _header->hideSection(KrViewProperties::KrPermissions); _header->hideSection(KrViewProperties::Owner); _header->hideSection(KrViewProperties::Group); _header->hideSection(KrViewProperties::Changed); _header->hideSection(KrViewProperties::Accessed); _header->setStretchLastSection(true); _header->setSectionResizeMode(QHeaderView::Fixed); _header->setSectionsClickable(true); _header->setSortIndicatorShown(true); connect(_header, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), _model, SLOT(sort(int,Qt::SortOrder))); _header->installEventFilter(this); _numOfColumns = _properties->numberOfColumns; setSortMode(_properties->sortColumn, (_properties->sortOptions & KrViewProperties::Descending)); } void KrInterBriefView::keyPressEvent(QKeyEvent *e) { if (!e || !_model->ready()) return ; // subclass bug if (handleKeyEvent(e)) return; QAbstractItemView::keyPressEvent(e); } bool KrInterBriefView::handleKeyEvent(QKeyEvent *e) { if ((e->key() != Qt::Key_Left && e->key() != Qt::Key_Right) && (KrView::handleKeyEvent(e))) // did the view class handled the event? return true; switch (e->key()) { case Qt::Key_Right : { if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); break; } KrViewItem *i = getCurrentKrViewItem(); KrViewItem *newCurrent = i; if (!i) break; int num = itemsPerPage() + 1; if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); while (i && num > 0) { if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); newCurrent = i; i = getNext(i); num--; } if (newCurrent) { setCurrentKrViewItem(newCurrent); makeCurrentVisible(); } if (e->modifiers() & Qt::ShiftModifier) op()->emitSelectionChanged(); return true; } case Qt::Key_Left : { if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); break; } KrViewItem *i = getCurrentKrViewItem(); KrViewItem *newCurrent = i; if (!i) break; int num = itemsPerPage() + 1; if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); while (i && num > 0) { if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); newCurrent = i; i = getPrev(i); num--; } if (newCurrent) { setCurrentKrViewItem(newCurrent); makeCurrentVisible(); } if (e->modifiers() & Qt::ShiftModifier) op()->emitSelectionChanged(); return true; } } return false; } void KrInterBriefView::wheelEvent(QWheelEvent *ev) { if (!_mouseHandler->wheelEvent(ev)) QApplication::sendEvent(horizontalScrollBar(), ev); } bool KrInterBriefView::eventFilter(QObject *object, QEvent *event) { if (object == _header) { if (event->type() == QEvent::ContextMenu) { QContextMenuEvent *me = (QContextMenuEvent *)event; showContextMenu(me->globalPos()); return true; } } return false; } void KrInterBriefView::showContextMenu(const QPoint & p) { QMenu popup(this); popup.setTitle(i18n("Columns")); int COL_ID = 14700; for (int i = 1; i <= MAX_BRIEF_COLS; i++) { QAction *act = popup.addAction(QString("%1").arg(i)); act->setData(QVariant(COL_ID + i)); act->setCheckable(true); act->setChecked(properties()->numberOfColumns == i); } QAction * res = popup.exec(p); int result = -1; if (res && res->data().canConvert()) result = res->data().toInt(); if (result > COL_ID && result <= COL_ID + MAX_BRIEF_COLS) { _properties->numberOfColumns = result - COL_ID; _numOfColumns = _properties->numberOfColumns; updateGeometries(); op()->settingsChanged(KrViewProperties::PropColumns); } } QRect KrInterBriefView::visualRect(const QModelIndex&ndx) const { int width = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) width++; int height = getItemHeight(); int numRows = viewport()->height() / height; if (numRows == 0) numRows++; int x = width * (ndx.row() / numRows); int y = height * (ndx.row() % numRows); return mapToViewport(QRect(x, y, width, height)); } void KrInterBriefView::scrollTo(const QModelIndex &ndx, QAbstractItemView::ScrollHint hint) { const QRect rect = visualRect(ndx); if (hint == EnsureVisible && viewport()->rect().contains(rect)) { setDirtyRegion(rect); return; } const QRect area = viewport()->rect(); const bool leftOf = rect.left() < area.left(); const bool rightOf = rect.right() > area.right(); int horizontalValue = horizontalScrollBar()->value(); if (leftOf) horizontalValue -= area.left() - rect.left(); else if (rightOf) horizontalValue += rect.right() - area.right(); horizontalScrollBar()->setValue(horizontalValue); } QModelIndex KrInterBriefView::indexAt(const QPoint& p) const { int x = p.x() + horizontalOffset(); int y = p.y() + verticalOffset(); int itemWidth = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) itemWidth++; int itemHeight = getItemHeight(); int numRows = viewport()->height() / itemHeight; if (numRows == 0) numRows++; int row = y / itemHeight; int col = x / itemWidth; int numColsTotal = _model->rowCount() / numRows; if(_model->rowCount() % numRows) numColsTotal++; if(row < numRows && col < numColsTotal) return _model->index((col * numRows) + row, 0); return QModelIndex(); } QModelIndex KrInterBriefView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers) { if (_model->rowCount() == 0) return QModelIndex(); QModelIndex current = currentIndex(); if (!current.isValid()) return _model->index(0, 0); switch (cursorAction) { case MoveLeft: case MovePageDown: { int newRow = current.row() - itemsPerPage(); if (newRow < 0) newRow = 0; return _model->index(newRow, 0); } case MoveRight: case MovePageUp: { int newRow = current.row() + itemsPerPage(); if (newRow >= _model->rowCount()) newRow = _model->rowCount() - 1; return _model->index(newRow, 0); } case MovePrevious: case MoveUp: { int newRow = current.row() - 1; if (newRow < 0) newRow = 0; return _model->index(newRow, 0); } case MoveNext: case MoveDown: { int newRow = current.row() + 1; if (newRow >= _model->rowCount()) newRow = _model->rowCount() - 1; return _model->index(newRow, 0); } case MoveHome: return _model->index(0, 0); case MoveEnd: return _model->index(_model->rowCount() - 1, 0); } return current; } int KrInterBriefView::horizontalOffset() const { return horizontalScrollBar()->value(); } int KrInterBriefView::verticalOffset() const { return 0; } bool KrInterBriefView::isIndexHidden(const QModelIndex&ndx) const { return ndx.column() != 0; } #if 0 QRegion KrInterBriefView::visualRegionForSelection(const QItemSelection &selection) const { if (selection.isEmpty()) return QRegion(); QRegion selectionRegion; for (int i = 0; i < selection.count(); ++i) { QItemSelectionRange range = selection.at(i); if (!range.isValid()) continue; QModelIndex leftIndex = range.topLeft(); if (!leftIndex.isValid()) continue; const QRect leftRect = visualRect(leftIndex); int top = leftRect.top(); QModelIndex rightIndex = range.bottomRight(); if (!rightIndex.isValid()) continue; const QRect rightRect = visualRect(rightIndex); int bottom = rightRect.bottom(); if (top > bottom) qSwap(top, bottom); int height = bottom - top + 1; QRect combined = leftRect | rightRect; combined.setX(range.left()); selectionRegion += combined; } return selectionRegion; } #endif void KrInterBriefView::paintEvent(QPaintEvent *e) { QStyleOptionViewItem option = viewOptions(); option.widget = this; option.decorationSize = QSize(_fileIconSize, _fileIconSize); option.decorationPosition = QStyleOptionViewItem::Left; QPainter painter(viewport()); QModelIndex curr = currentIndex(); QVector intersectVector; QRect area = e->rect(); area.adjust(horizontalOffset(), verticalOffset(), horizontalOffset(), verticalOffset()); intersectionSet(area, intersectVector); foreach(const QModelIndex &mndx, intersectVector) { option.state = QStyle::State_None; option.rect = visualRect(mndx); painter.save(); itemDelegate()->paint(&painter, option, mndx); // (always) draw dashed line border around current item row const bool isCurrent = curr.isValid() && curr.row() == mndx.row(); if (isCurrent && drawCurrent()) { QStyleOptionFocusRect o; o.QStyleOption::operator=(option); QPalette::ColorGroup cg = QPalette::Normal; o.backgroundColor = option.palette.color(cg, QPalette::Background); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, &painter); } painter.restore(); } } int KrInterBriefView::getItemHeight() const { int textHeight = QFontMetrics(_viewFont).height(); int height = textHeight; int iconSize = 0; if (properties()->displayIcons) iconSize = _fileIconSize; if (iconSize > textHeight) height = iconSize; if (height == 0) height++; return height; } void KrInterBriefView::updateGeometries() { if (_header) { QSize hint = _header->sizeHint(); setViewportMargins(0, hint.height(), 0, 0); QRect vg = viewport()->geometry(); QRect geometryRect(vg.left(), vg.top() - hint.height(), vg.width(), hint.height()); _header->setGeometry(geometryRect); int items = 0; for (int i = 0; i != _header->count(); i++) if (!_header->isSectionHidden(i)) items++; if (items == 0) items++; int sectWidth = viewport()->width() / items; for (int i = 0; i != _header->count(); i++) if (!_header->isSectionHidden(i)) _header->resizeSection(i, sectWidth); QMetaObject::invokeMethod(_header, "updateGeometries"); } if (_model->rowCount() <= 0) horizontalScrollBar()->setRange(0, 0); else { int itemsPerColumn = viewport()->height() / getItemHeight(); if (itemsPerColumn <= 0) itemsPerColumn = 1; int columnWidth = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) columnWidth++; int maxWidth = _model->rowCount() / itemsPerColumn; if (_model->rowCount() % itemsPerColumn) maxWidth++; maxWidth *= columnWidth; if (maxWidth > viewport()->width()) { horizontalScrollBar()->setSingleStep(columnWidth); horizontalScrollBar()->setPageStep(columnWidth * _numOfColumns); horizontalScrollBar()->setRange(0, maxWidth - viewport()->width()); } else { horizontalScrollBar()->setRange(0, 0); } } QAbstractItemView::updateGeometries(); } void KrInterBriefView::setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) { Qt::SortOrder sortDir = descending ? Qt::DescendingOrder : Qt::AscendingOrder; _header->setSortIndicator(sortColumn, sortDir); } int KrInterBriefView::elementWidth(const QModelIndex & index) { QString text = index.data(Qt::DisplayRole).toString(); int textWidth = QFontMetrics(_viewFont).width(text); const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; textWidth += 2 * textMargin; QVariant decor = index.data(Qt::DecorationRole); if (decor.isValid() && decor.type() == QVariant::Pixmap) { QPixmap p = decor.value(); textWidth += p.width() + 2 * textMargin; } return textWidth; } void KrInterBriefView::intersectionSet(const QRect &rect, QVector &ndxList) { int maxNdx = _model->rowCount(); int width = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) width++; int height = getItemHeight(); int items = viewport()->height() / height; if (items == 0) items++; int xmin = -1; int ymin = -1; int xmax = -1; int ymax = -1; xmin = rect.x() / width; ymin = rect.y() / height; xmax = (rect.x() + rect.width()) / width; if ((rect.x() + rect.width()) % width) xmax++; ymax = (rect.y() + rect.height()) / height; if ((rect.y() + rect.height()) % height) ymax++; for (int i = ymin; i < ymax; i++) for (int j = xmin; j < xmax; j++) { int ndx = j * items + i; if (ndx < maxNdx) ndxList.append(_model->index(ndx, 0)); } } QRect KrInterBriefView::itemRect(const FileItem *item) { return visualRect(_model->fileItemIndex(item)); } void KrInterBriefView::copySettingsFrom(KrView *other) { if(other->instance() == instance()) { // the other view is of the same type KrInterBriefView *v = static_cast(other); int column = v->_model->lastSortOrder(); Qt::SortOrder sortDir = v->_model->lastSortDir(); _header->setSortIndicator(column, sortDir); _model->sort(column, sortDir); setFileIconSize(v->fileIconSize()); } } void KrInterBriefView::setFileIconSize(int size) { KrView::setFileIconSize(size); setIconSize(QSize(fileIconSize(), fileIconSize())); updateGeometries(); } void KrInterBriefView::currentChanged(const QModelIndex & current, const QModelIndex & previous) { if (_model->ready()) { KrViewItem * item = getKrViewItem(currentIndex()); op()->emitCurrentChanged(item); } QAbstractItemView::currentChanged(current, previous); } void KrInterBriefView::renameCurrentItem() { QModelIndex cIndex = currentIndex(); QModelIndex nameIndex = _model->index(cIndex.row(), KrViewProperties::Name); edit(nameIndex); updateEditorData(); update(nameIndex); } bool KrInterBriefView::event(QEvent * e) { _mouseHandler->otherEvent(e); return QAbstractItemView::event(e); } void KrInterBriefView::mousePressEvent(QMouseEvent * ev) { if (!_mouseHandler->mousePressEvent(ev)) QAbstractItemView::mousePressEvent(ev); } void KrInterBriefView::mouseReleaseEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseReleaseEvent(ev)) QAbstractItemView::mouseReleaseEvent(ev); } void KrInterBriefView::mouseDoubleClickEvent(QMouseEvent *ev) { if (!_mouseHandler->mouseDoubleClickEvent(ev)) QAbstractItemView::mouseDoubleClickEvent(ev); } void KrInterBriefView::mouseMoveEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseMoveEvent(ev)) QAbstractItemView::mouseMoveEvent(ev); } void KrInterBriefView::dragEnterEvent(QDragEnterEvent *ev) { if (!_mouseHandler->dragEnterEvent(ev)) QAbstractItemView::dragEnterEvent(ev); } void KrInterBriefView::dragMoveEvent(QDragMoveEvent *ev) { QAbstractItemView::dragMoveEvent(ev); _mouseHandler->dragMoveEvent(ev); } void KrInterBriefView::dragLeaveEvent(QDragLeaveEvent *ev) { if (!_mouseHandler->dragLeaveEvent(ev)) QAbstractItemView::dragLeaveEvent(ev); } void KrInterBriefView::dropEvent(QDropEvent *ev) { if (!_mouseHandler->dropEvent(ev)) QAbstractItemView::dropEvent(ev); } QRect KrInterBriefView::mapToViewport(const QRect &rect) const { if (!rect.isValid()) return rect; QRect result = rect; int dx = -horizontalOffset(); int dy = -verticalOffset(); result.adjust(dx, dy, dx, dy); return result; } diff --git a/krusader/Panel/krinterbriefview.h b/krusader/Panel/PanelView/krinterbriefview.h similarity index 100% rename from krusader/Panel/krinterbriefview.h rename to krusader/Panel/PanelView/krinterbriefview.h diff --git a/krusader/Panel/krinterdetailedview.cpp b/krusader/Panel/PanelView/krinterdetailedview.cpp similarity index 99% rename from krusader/Panel/krinterdetailedview.cpp rename to krusader/Panel/PanelView/krinterdetailedview.cpp index 8c9090ff..f46f2462 100644 --- a/krusader/Panel/krinterdetailedview.cpp +++ b/krusader/Panel/PanelView/krinterdetailedview.cpp @@ -1,438 +1,438 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krinterdetailedview.h" // QtCore #include #include // QtWidgets #include #include #include #include #include #include #include #include #include "krviewfactory.h" #include "krviewitemdelegate.h" #include "krviewitem.h" #include "listmodel.h" #include "../FileSystem/krpermhandler.h" #include "../defaults.h" #include "../krglobal.h" #include "krmousehandler.h" -#include "krcolorcache.h" +#include "../krcolorcache.h" #include "../GUI/krstyleproxy.h" KrInterDetailedView::KrInterDetailedView(QWidget *parent, KrViewInstance &instance, KConfig *cfg): QTreeView(parent), KrInterView(instance, cfg, this), _autoResizeColumns(true) { connect(_mouseHandler, SIGNAL(renameCurrentItem()), this, SLOT(renameCurrentItem())); setWidget(this); KConfigGroup grpSvr(_config, "Look&Feel"); _viewFont = grpSvr.readEntry("Filelist Font", _FilelistFont); setModel(_model); setRootIsDecorated(false); setItemsExpandable(false); setAllColumnsShowFocus(true); setUniformRowHeights(true); setMouseTracking(true); setAcceptDrops(true); setDropIndicatorShown(true); setSelectionMode(QAbstractItemView::NoSelection); setSelectionModel(new DummySelectionModel(_model, this)); header()->installEventFilter(this); header()->setSectionResizeMode(QHeaderView::Interactive); header()->setStretchLastSection(false); KrStyleProxy *style = new KrStyleProxy(); style->setParent(this); setStyle(style); viewport()->setStyle(style); // for custom tooltip delay setItemDelegate(new KrViewItemDelegate(this)); connect(header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(sectionResized(int,int,int))); connect(header(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(sectionMoved(int,int,int))); } KrInterDetailedView::~KrInterDetailedView() { delete _properties; _properties = 0; delete _operator; _operator = 0; } void KrInterDetailedView::currentChanged(const QModelIndex & current, const QModelIndex & previous) { if (_model->ready()) { KrViewItem * item = getKrViewItem(currentIndex()); op()->emitCurrentChanged(item); } QTreeView::currentChanged(current, previous); } void KrInterDetailedView::doRestoreSettings(KConfigGroup grp) { _autoResizeColumns = grp.readEntry("AutoResizeColumns", true); QByteArray savedState = grp.readEntry("Saved State", QByteArray()); if (savedState.isEmpty()) { hideColumn(KrViewProperties::Type); hideColumn(KrViewProperties::Permissions); hideColumn(KrViewProperties::Owner); hideColumn(KrViewProperties::Group); hideColumn(KrViewProperties::Changed); hideColumn(KrViewProperties::Accessed); header()->resizeSection(KrViewProperties::Ext, QFontMetrics(_viewFont).width("tar.bz2 ")); header()->resizeSection(KrViewProperties::KrPermissions, QFontMetrics(_viewFont).width("rwx ")); header()->resizeSection(KrViewProperties::Size, QFontMetrics(_viewFont).width("9") * 10); QDateTime tmp(QDate(2099, 12, 29), QTime(23, 59)); QString desc = QLocale().toString(tmp, QLocale::ShortFormat) + " "; header()->resizeSection(KrViewProperties::Modified, QFontMetrics(_viewFont).width(desc)); } else { header()->restoreState(savedState); // do not show new columns by default; restoreState() shows columns not saved if (KrGlobal::sCurrentConfigVersion < KrGlobal::sConfigVersion) { hideColumn(KrViewProperties::Changed); hideColumn(KrViewProperties::Accessed); } _model->setExtensionEnabled(!isColumnHidden(KrViewProperties::Ext)); } KrInterView::doRestoreSettings(grp); } void KrInterDetailedView::saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) { KrInterView::saveSettings(grp, properties); grp.writeEntry("AutoResizeColumns", _autoResizeColumns); if(properties & KrViewProperties::PropColumns) { QByteArray state = header()->saveState(); grp.writeEntry("Saved State", state); } } int KrInterDetailedView::itemsPerPage() { QRect rect = visualRect(currentIndex()); if (!rect.isValid()) { for (int i = 0; i != _model->rowCount(); i++) { rect = visualRect(_model->index(i, 0)); if (rect.isValid()) break; } } if (!rect.isValid()) return 0; int size = (height() - header()->height()) / rect.height(); if (size < 0) size = 0; return size; } void KrInterDetailedView::updateView() { } void KrInterDetailedView::setup() { setSortMode(_properties->sortColumn, (_properties->sortOptions & KrViewProperties::Descending)); setSortingEnabled(true); } void KrInterDetailedView::keyPressEvent(QKeyEvent *e) { if (!e || !_model->ready()) return ; // subclass bug if (handleKeyEvent(e)) // did the view class handled the event? return; QTreeView::keyPressEvent(e); } void KrInterDetailedView::mousePressEvent(QMouseEvent * ev) { if (!_mouseHandler->mousePressEvent(ev)) QTreeView::mousePressEvent(ev); } void KrInterDetailedView::mouseReleaseEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseReleaseEvent(ev)) QTreeView::mouseReleaseEvent(ev); } void KrInterDetailedView::mouseDoubleClickEvent(QMouseEvent *ev) { if (!_mouseHandler->mouseDoubleClickEvent(ev)) QTreeView::mouseDoubleClickEvent(ev); } void KrInterDetailedView::mouseMoveEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseMoveEvent(ev)) QTreeView::mouseMoveEvent(ev); } void KrInterDetailedView::wheelEvent(QWheelEvent *ev) { if (!_mouseHandler->wheelEvent(ev)) QTreeView::wheelEvent(ev); } void KrInterDetailedView::dragEnterEvent(QDragEnterEvent *ev) { if (!_mouseHandler->dragEnterEvent(ev)) QTreeView::dragEnterEvent(ev); } void KrInterDetailedView::dragMoveEvent(QDragMoveEvent *ev) { QTreeView::dragMoveEvent(ev); _mouseHandler->dragMoveEvent(ev); } void KrInterDetailedView::dragLeaveEvent(QDragLeaveEvent *ev) { if (!_mouseHandler->dragLeaveEvent(ev)) QTreeView::dragLeaveEvent(ev); } void KrInterDetailedView::dropEvent(QDropEvent *ev) { if (!_mouseHandler->dropEvent(ev)) QTreeView::dropEvent(ev); } bool KrInterDetailedView::event(QEvent * e) { _mouseHandler->otherEvent(e); return QTreeView::event(e); } void KrInterDetailedView::renameCurrentItem() { QModelIndex cIndex = currentIndex(); QModelIndex nameIndex = _model->index(cIndex.row(), KrViewProperties::Name); edit(nameIndex); updateEditorData(); update(nameIndex); } bool KrInterDetailedView::eventFilter(QObject *object, QEvent *event) { if (object == header()) { if (event->type() == QEvent::ContextMenu) { QContextMenuEvent *me = (QContextMenuEvent *)event; showContextMenu(me->globalPos()); return true; } else if (event->type() == QEvent::Resize) { recalculateColumnSizes(); return false; } } return false; } void KrInterDetailedView::showContextMenu(const QPoint & p) { QMenu popup(this); popup.setTitle(i18n("Columns")); QVector actions; for(int i = KrViewProperties::Ext; i < KrViewProperties::MAX_COLUMNS; i++) { QString text = (_model->headerData(i, Qt::Horizontal)).toString(); QAction *act = popup.addAction(text); act->setCheckable(true); act->setChecked(!header()->isSectionHidden(i)); act->setData(i); actions.append(act); } popup.addSeparator(); QAction *actAutoResize = popup.addAction(i18n("Automatically Resize Columns")); actAutoResize->setCheckable(true); actAutoResize->setChecked(_autoResizeColumns); QAction *res = popup.exec(p); if (res == 0) return; if(res == actAutoResize) { _autoResizeColumns = actAutoResize->isChecked(); recalculateColumnSizes(); } else { int column = res->data().toInt(); if(header()->isSectionHidden(column)) header()->showSection(column); else header()->hideSection(column); if(KrViewProperties::Ext == column) _model->setExtensionEnabled(!header()->isSectionHidden(KrViewProperties::Ext)); } op()->settingsChanged(KrViewProperties::PropColumns); } void KrInterDetailedView::sectionResized(int /*column*/, int oldSize, int newSize) { // *** taken from dolphin *** // If the user changes the size of the headers, the autoresize feature should be // turned off. As there is no dedicated interface to find out whether the header // section has been resized by the user or by a resize event, another approach is used. // Attention: Take care when changing the if-condition to verify that there is no // regression in combination with bug 178630 (see fix in comment #8). if ((QApplication::mouseButtons() & Qt::LeftButton) && header()->underMouse()) { _autoResizeColumns = false; op()->settingsChanged(KrViewProperties::PropColumns); } if (oldSize == newSize || !_model->ready()) return; recalculateColumnSizes(); } void KrInterDetailedView::sectionMoved(int /*logicalIndex*/, int /*oldVisualIndex*/, int /*newVisualIndex*/) { op()->settingsChanged(KrViewProperties::PropColumns); } void KrInterDetailedView::recalculateColumnSizes() { if(!_autoResizeColumns) return; int sum = 0; for (int i = 0; i != _model->columnCount(); i++) { if (!isColumnHidden(i)) sum += header()->sectionSize(i); } if (sum != header()->width()) { int delta = sum - header()->width(); int nameSize = header()->sectionSize(KrViewProperties::Name); if (nameSize - delta > 20) header()->resizeSection(KrViewProperties::Name, nameSize - delta); } } bool KrInterDetailedView::viewportEvent(QEvent * event) { if (event->type() == QEvent::ToolTip) { // only show tooltip if column is not wide enough to show all text. In this case the column // data text is abbreviated and the full text is shown as tooltip, see ListModel::data(). QHelpEvent *he = static_cast(event); const QModelIndex index = indexAt(he->pos()); // name column has a detailed tooltip if (index.isValid() && index.column() != KrViewProperties::Name) { int width = header()->sectionSize(index.column()); QString text = index.data(Qt::DisplayRole).toString(); int textWidth = QFontMetrics(_viewFont).width(text); const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; textWidth += 2 * textMargin; QVariant decor = index.data(Qt::DecorationRole); if (decor.isValid() && decor.type() == QVariant::Pixmap) { QPixmap p = decor.value(); textWidth += p.width() + 2 * textMargin; } if (textWidth <= width) { QToolTip::hideText(); event->accept(); return true; } } } return QTreeView::viewportEvent(event); } void KrInterDetailedView::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const { QTreeView::drawRow(painter, options, index); // (may) draw dashed line border around current item row. This is done internally in // QTreeView::drawRow() only when panel is focused, we have to repeat it here. if (index == currentIndex() && drawCurrent()) { QStyleOptionFocusRect o; o.backgroundColor = options.palette.color(QPalette::Normal, QPalette::Background); const QRect focusRect(0, options.rect.y(), header()->length(), options.rect.height()); o.rect = style()->visualRect(layoutDirection(), viewport()->rect(), focusRect); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter); } } void KrInterDetailedView::setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) { Qt::SortOrder sortDir = descending ? Qt::DescendingOrder : Qt::AscendingOrder; sortByColumn(sortColumn, sortDir); } void KrInterDetailedView::setFileIconSize(int size) { KrView::setFileIconSize(size); setIconSize(QSize(fileIconSize(), fileIconSize())); } QRect KrInterDetailedView::itemRect(const FileItem *item) { QRect r = visualRect(_model->fileItemIndex(item)); r.setLeft(0); r.setWidth(header()->length()); return r; } void KrInterDetailedView::copySettingsFrom(KrView *other) { if(other->instance() == instance()) { // the other view is of the same type KrInterDetailedView *v = static_cast(other); _autoResizeColumns = v->_autoResizeColumns; header()->restoreState(v->header()->saveState()); _model->setExtensionEnabled(!isColumnHidden(KrViewProperties::Ext)); recalculateColumnSizes(); setFileIconSize(v->fileIconSize()); } } diff --git a/krusader/Panel/krinterdetailedview.h b/krusader/Panel/PanelView/krinterdetailedview.h similarity index 100% rename from krusader/Panel/krinterdetailedview.h rename to krusader/Panel/PanelView/krinterdetailedview.h diff --git a/krusader/Panel/krinterview.cpp b/krusader/Panel/PanelView/krinterview.cpp similarity index 99% rename from krusader/Panel/krinterview.cpp rename to krusader/Panel/PanelView/krinterview.cpp index cfef3244..61dc7878 100644 --- a/krusader/Panel/krinterview.cpp +++ b/krusader/Panel/PanelView/krinterview.cpp @@ -1,386 +1,386 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2010 Jan Lepper * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krinterview.h" -#include "krcolorcache.h" #include "krmousehandler.h" -#include "krpreviews.h" #include "listmodel.h" #include "krviewitem.h" +#include "../krpreviews.h" +#include "../krcolorcache.h" #include "../FileSystem/dirlisterinterface.h" #include "../FileSystem/fileitem.h" KrInterView::KrInterView(KrViewInstance &instance, KConfig *cfg, QAbstractItemView *itemView) : KrView(instance, cfg), _itemView(itemView), _mouseHandler(0) { _model = new ListModel(this); // fix the context menu problem int j = QFontMetrics(_itemView->font()).height() * 2; _mouseHandler = new KrMouseHandler(this, j); } KrInterView::~KrInterView() { // any references to the model should be cleared ar this point, // but sometimes for some reason it is still referenced by // QPersistentModelIndex instances held by QAbstractItemView and/or QItemSelectionModel(child object) - // so schedule _model for later deletion _model->clear(false); _model->deleteLater(); _model = 0; delete _mouseHandler; _mouseHandler = 0; QHashIterator< FileItem *, KrViewItem *> it(_itemHash); while (it.hasNext()) delete it.next().value(); _itemHash.clear(); } void KrInterView::selectRegion(KrViewItem *i1, KrViewItem *i2, bool select) { FileItem* file1 = (FileItem *)i1->getFileItem(); QModelIndex mi1 = _model->fileItemIndex(file1); FileItem* file2 = (FileItem *)i2->getFileItem(); QModelIndex mi2 = _model->fileItemIndex(file2); if (mi1.isValid() && mi2.isValid()) { int r1 = mi1.row(); int r2 = mi2.row(); if (r1 > r2) { int t = r1; r1 = r2; r2 = t; } op()->setMassSelectionUpdate(true); for (int row = r1; row <= r2; row++) setSelected(_model->fileItemAt(_model->index(row, 0)), select); op()->setMassSelectionUpdate(false); redraw(); } else if (mi1.isValid() && !mi2.isValid()) i1->setSelected(select); else if (mi2.isValid() && !mi1.isValid()) i2->setSelected(select); } void KrInterView::intSetSelected(const FileItem* item, bool select) { if(select) _selection.insert(item); else _selection.remove(item); } bool KrInterView::isSelected(const QModelIndex &ndx) { return isSelected(_model->fileItemAt(ndx)); } KrViewItem* KrInterView::findItemByName(const QString &name) { if (!_model->ready()) return 0; QModelIndex ndx = _model->nameIndex(name); if (!ndx.isValid()) return 0; return getKrViewItem(ndx); } KrViewItem *KrInterView::findItemByUrl(const QUrl &url) { if (!_model->ready()) return 0; const QModelIndex ndx = _model->indexFromUrl(url); if (!ndx.isValid()) return 0; return getKrViewItem(ndx); } QString KrInterView::getCurrentItem() const { if (!_model->ready()) return QString(); FileItem *fileitem = _model->fileItemAt(_itemView->currentIndex()); if (fileitem == 0) return QString(); return fileitem->getName(); } KrViewItem* KrInterView::getCurrentKrViewItem() { if (!_model->ready()) return 0; return getKrViewItem(_itemView->currentIndex()); } KrViewItem* KrInterView::getFirst() { if (!_model->ready()) return 0; return getKrViewItem(_model->index(0, 0, QModelIndex())); } KrViewItem* KrInterView::getLast() { if (!_model->ready()) return 0; return getKrViewItem(_model->index(_model->rowCount() - 1, 0, QModelIndex())); } KrViewItem* KrInterView::getNext(KrViewItem *current) { FileItem* fileItem = (FileItem *)current->getFileItem(); QModelIndex ndx = _model->fileItemIndex(fileItem); if (ndx.row() >= _model->rowCount() - 1) return 0; return getKrViewItem(_model->index(ndx.row() + 1, 0, QModelIndex())); } KrViewItem* KrInterView::getPrev(KrViewItem *current) { FileItem* fileItem = (FileItem *)current->getFileItem(); QModelIndex ndx = _model->fileItemIndex(fileItem); if (ndx.row() <= 0) return 0; return getKrViewItem(_model->index(ndx.row() - 1, 0, QModelIndex())); } KrViewItem* KrInterView::getKrViewItemAt(const QPoint &vp) { if (!_model->ready()) return 0; return getKrViewItem(_itemView->indexAt(vp)); } KrViewItem *KrInterView::findItemByFileItem(FileItem *fileItem) { return getKrViewItem(fileItem); } KrViewItem * KrInterView::getKrViewItem(FileItem *fileItem) { QHash::iterator it = _itemHash.find(fileItem); if (it == _itemHash.end()) { KrViewItem * newItem = new KrViewItem(fileItem, this); _itemHash[ fileItem ] = newItem; return newItem; } return *it; } KrViewItem * KrInterView::getKrViewItem(const QModelIndex & ndx) { if (!ndx.isValid()) return 0; FileItem * fileitem = _model->fileItemAt(ndx); if (fileitem == 0) return 0; else return getKrViewItem(fileitem); } void KrInterView::makeCurrentVisible() { _itemView->scrollTo(_itemView->currentIndex()); } void KrInterView::makeItemVisible(const KrViewItem *item) { if (item == 0) return; FileItem* fileitem = (FileItem *)item->getFileItem(); QModelIndex ndx = _model->fileItemIndex(fileitem); if (ndx.isValid()) _itemView->scrollTo(ndx); } bool KrInterView::isItemVisible(const KrViewItem *item) { return _itemView->viewport()->rect().contains(item->itemRect()); } void KrInterView::setCurrentItem(const QString& name, const QModelIndex &fallbackToIndex) { // find index by given name and set it as current QModelIndex ndx = _model->nameIndex(name); if (ndx.isValid()) { // also sets the scrolling position _itemView->setCurrentIndex(ndx); } else if (fallbackToIndex.isValid()) { // set fallback index as current index // when fallback index is too big, set the last item as current if (fallbackToIndex.row() >= _itemView->model()->rowCount()) { setCurrentKrViewItem(getLast()); } else { _itemView->setCurrentIndex(fallbackToIndex); } } else { // when given parameters fail, set the first item as current setCurrentKrViewItem(getFirst()); } } void KrInterView::setCurrentKrViewItem(KrViewItem *item) { if (item == 0) { _itemView->setCurrentIndex(QModelIndex()); return; } FileItem* fileitem = (FileItem *)item->getFileItem(); QModelIndex ndx = _model->fileItemIndex(fileitem); if (ndx.isValid() && ndx.row() != _itemView->currentIndex().row()) { _mouseHandler->cancelTwoClickRename(); _itemView->setCurrentIndex(ndx); } } void KrInterView::sort() { _model->sort(); } void KrInterView::clear() { _selection.clear(); _itemView->clearSelection(); _itemView->setCurrentIndex(QModelIndex()); _model->clear(); QHashIterator< FileItem *, KrViewItem *> it(_itemHash); while (it.hasNext()) delete it.next().value(); _itemHash.clear(); KrView::clear(); } void KrInterView::populate(const QList &fileItems, FileItem *dummy) { _model->populate(fileItems, dummy); } KrViewItem* KrInterView::preAddItem(FileItem *fileitem) { QModelIndex idx = _model->addItem(fileitem); if(_model->rowCount() == 1) // if this is the fist item to be added, make it current _itemView->setCurrentIndex(idx); return getKrViewItem(idx); } void KrInterView::preDelItem(KrViewItem *item) { setSelected(item->getFileItem(), false); QModelIndex ndx = _model->removeItem((FileItem *)item->getFileItem()); if (ndx.isValid()) _itemView->setCurrentIndex(ndx); _itemHash.remove((FileItem *)item->getFileItem()); } void KrInterView::prepareForActive() { _focused = true; _itemView->setFocus(); } void KrInterView::prepareForPassive() { _focused = false; _mouseHandler->cancelTwoClickRename(); //if ( renameLineEdit() ->isVisible() ) //renameLineEdit() ->clearFocus(); } void KrInterView::redraw() { _itemView->viewport()->update(); } void KrInterView::refreshColors() { QPalette p(_itemView->palette()); KrColorGroup cg; KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, false, _focused, false, false)); p.setColor(QPalette::Text, cg.text()); p.setColor(QPalette::Base, cg.background()); _itemView->setPalette(p); redraw(); } void KrInterView::sortModeUpdated(int column, Qt::SortOrder order) { KrView::sortModeUpdated(static_cast(column), order == Qt::DescendingOrder); } KIO::filesize_t KrInterView::calcSize() { KIO::filesize_t size = 0; foreach(FileItem *fileitem, _model->fileItems()) { size += fileitem->getSize(); } return size; } KIO::filesize_t KrInterView::calcSelectedSize() { KIO::filesize_t size = 0; foreach(const FileItem *fileitem, _selection) { size += fileitem->getSize(); } return size; } QList KrInterView::selectedUrls() { QList list; foreach(const FileItem *fileitem, _selection) { list << fileitem->getUrl(); } return list; } void KrInterView::setSelectionUrls(const QList urls) { op()->setMassSelectionUpdate(true); _selection.clear(); foreach(const QUrl &url, urls) { const QModelIndex idx = _model->indexFromUrl(url); if(idx.isValid()) setSelected(_model->fileItemAt(idx), true); } op()->setMassSelectionUpdate(false); } diff --git a/krusader/Panel/krinterview.h b/krusader/Panel/PanelView/krinterview.h similarity index 100% rename from krusader/Panel/krinterview.h rename to krusader/Panel/PanelView/krinterview.h diff --git a/krusader/Panel/krmousehandler.cpp b/krusader/Panel/PanelView/krmousehandler.cpp similarity index 100% rename from krusader/Panel/krmousehandler.cpp rename to krusader/Panel/PanelView/krmousehandler.cpp index 70d51b1f..c0c210b0 100644 --- a/krusader/Panel/krmousehandler.cpp +++ b/krusader/Panel/PanelView/krmousehandler.cpp @@ -1,385 +1,385 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krmousehandler.h" +#include "krselectionmode.h" #include "krview.h" #include "krviewitem.h" -#include "krselectionmode.h" -#include "../krglobal.h" #include "../defaults.h" +#include "../krglobal.h" // QtCore #include // QtWidgets #include #include #include #include #define CANCEL_TWO_CLICK_RENAME {_singleClicked = false;_renameTimer.stop();} KrMouseHandler::KrMouseHandler(KrView * view, int contextMenuShift) : _view(view), _rightClickedItem(0), _contextMenuTimer(), _contextMenuShift(contextMenuShift), _singleClicked(false), _singleClickTime(), _renameTimer(), _dragStartPos(-1, -1), _emptyContextMenu(false), _selectedItemNames() { KConfigGroup grpSvr(krConfig, "Look&Feel"); // decide on single click/double click selection bool singleClickTmp = QApplication::style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick); _singleClick = grpSvr.readEntry("Single Click Selects", _SingleClickSelects) && singleClickTmp; connect(&_contextMenuTimer, SIGNAL(timeout()), this, SLOT(showContextMenu())); connect(&_renameTimer, SIGNAL(timeout()), this, SIGNAL(renameCurrentItem())); } bool KrMouseHandler::mousePressEvent(QMouseEvent *e) { _rightClickedItem = _clickedItem = 0; KrViewItem * item = _view->getKrViewItemAt(e->pos()); if (!_view->isFocused()) _view->op()->emitNeedFocus(); if (e->button() == Qt::LeftButton) { _dragStartPos = e->pos(); if (e->modifiers() == Qt::NoModifier) { if (item) { if (KrSelectionMode::getSelectionHandler()->leftButtonSelects()) { if (KrSelectionMode::getSelectionHandler()->leftButtonPreservesSelection()) item->setSelected(!item->isSelected()); else { if (item->isSelected()) _clickedItem = item; else { // clear the current selection _view->changeSelection(KRQuery("*"), false, true); item->setSelected(true); } } } _view->setCurrentKrViewItem(item); } else { // empty space under items clicked if (KrSelectionMode::getSelectionHandler()->leftButtonSelects() && !KrSelectionMode::getSelectionHandler()->leftButtonPreservesSelection()) { // clear the current selection _view->changeSelection(KRQuery("*"), false, true); } } e->accept(); return true; } else if (e->modifiers() == Qt::ControlModifier) { if (item && (KrSelectionMode::getSelectionHandler()->shiftCtrlLeftButtonSelects() || KrSelectionMode::getSelectionHandler()->leftButtonSelects())) { // get current selected item names _selectedItemNames.clear(); _view->getSelectedItems(&_selectedItemNames, false); item->setSelected(!item->isSelected()); // select also the focused item if there are no other selected items KrViewItem * previousItem = _view->getCurrentKrViewItem(); if (previousItem->name() != ".." && _selectedItemNames.empty()) { previousItem->setSelected(true); } } if (item) { _view->setCurrentKrViewItem(item); } e->accept(); return true; } else if (e->modifiers() == Qt::ShiftModifier) { if (item && (KrSelectionMode::getSelectionHandler()->shiftCtrlLeftButtonSelects() || KrSelectionMode::getSelectionHandler()->leftButtonSelects())) { KrViewItem * current = _view->getCurrentKrViewItem(); if (current != 0) _view->selectRegion(item, current, true); } if (item) _view->setCurrentKrViewItem(item); e->accept(); return true; } } if (e->button() == Qt::RightButton) { //dragStartPos = e->pos(); if (e->modifiers() == Qt::NoModifier) { if (item) { if (KrSelectionMode::getSelectionHandler()->rightButtonSelects()) { if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection()) { if (KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0) { _rightClickSelects = !item->isSelected(); _rightClickedItem = item; } item->setSelected(!item->isSelected()); } else { if (item->isSelected()) { _clickedItem = item; } else { // clear the current selection _view->changeSelection(KRQuery("*"), false, true); item->setSelected(true); } } } _view->setCurrentKrViewItem(item); } handleContextMenu(item, e->globalPos()); e->accept(); return true; } else if (e->modifiers() == Qt::ControlModifier) { if (item && (KrSelectionMode::getSelectionHandler()->shiftCtrlRightButtonSelects() || KrSelectionMode::getSelectionHandler()->rightButtonSelects())) { item->setSelected(!item->isSelected()); } if (item) _view->setCurrentKrViewItem(item); e->accept(); return true; } else if (e->modifiers() == Qt::ShiftModifier) { if (item && (KrSelectionMode::getSelectionHandler()->shiftCtrlRightButtonSelects() || KrSelectionMode::getSelectionHandler()->rightButtonSelects())) { KrViewItem * current = _view->getCurrentKrViewItem(); if (current != 0) _view->selectRegion(item, current, true); } if (item) _view->setCurrentKrViewItem(item); e->accept(); return true; } } if (e->button() == Qt::ForwardButton) { _view->op()->emitGoForward(); return true; } if (e->button() == Qt::BackButton) { _view->op()->emitGoBack(); return true; } return false; } bool KrMouseHandler::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) _dragStartPos = QPoint(-1, -1); KrViewItem * item = _view->getKrViewItemAt(e->pos()); if (item && item == _clickedItem) { if (((e->button() == Qt::LeftButton) && (e->modifiers() == Qt::NoModifier) && (KrSelectionMode::getSelectionHandler()->leftButtonSelects()) && !(KrSelectionMode::getSelectionHandler()->leftButtonPreservesSelection())) || ((e->button() == Qt::RightButton) && (e->modifiers() == Qt::NoModifier) && (KrSelectionMode::getSelectionHandler()->rightButtonSelects()) && !(KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection()))) { // clear the current selection _view->changeSelection(KRQuery("*"), false, true); item->setSelected(true); } } if (e->button() == Qt::RightButton) { _rightClickedItem = 0; _contextMenuTimer.stop(); } if (_singleClick && e->button() == Qt::LeftButton && e->modifiers() == Qt::NoModifier) { CANCEL_TWO_CLICK_RENAME; e->accept(); if (item == 0) return true; QString tmp = item->name(); _view->op()->emitExecuted(tmp); return true; } else if (!_singleClick && e->button() == Qt::LeftButton) { if (item && e->modifiers() == Qt::NoModifier) { if (_singleClicked && !_renameTimer.isActive() && _singleClickedItem == item) { KSharedConfigPtr config = KSharedConfig::openConfig(); KConfigGroup group(krConfig, "KDE"); int doubleClickInterval = group.readEntry("DoubleClickInterval", 400); int msecsFromLastClick = _singleClickTime.msecsTo(QTime::currentTime()); if (msecsFromLastClick > doubleClickInterval && msecsFromLastClick < 5 * doubleClickInterval) { _singleClicked = false; _renameTimer.setSingleShot(true); _renameTimer.start(doubleClickInterval); return true; } } CANCEL_TWO_CLICK_RENAME; _singleClicked = true; _singleClickedItem = item; _singleClickTime = QTime::currentTime(); return true; } } CANCEL_TWO_CLICK_RENAME; if (e->button() == Qt::MidButton && item != 0) { e->accept(); if (item == 0) return true; _view->op()->emitMiddleButtonClicked(item); return true; } return false; } bool KrMouseHandler::mouseDoubleClickEvent(QMouseEvent *e) { CANCEL_TWO_CLICK_RENAME; KrViewItem * item = _view->getKrViewItemAt(e->pos()); if (_singleClick) return false; if (e->button() == Qt::LeftButton && item != 0) { e->accept(); QString tmp = item->name(); _view->op()->emitExecuted(tmp); return true; } return false; } bool KrMouseHandler::mouseMoveEvent(QMouseEvent *e) { KrViewItem * item = _view->getKrViewItemAt(e->pos()); if ((_singleClicked || _renameTimer.isActive()) && item != _singleClickedItem) CANCEL_TWO_CLICK_RENAME; if (!item) return false; const QString desc = item->description(); _view->op()->emitItemDescription(desc); if (_dragStartPos != QPoint(-1, -1) && (e->buttons() & Qt::LeftButton) && (_dragStartPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) { _view->op()->startDrag(); return true; } if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() && KrSelectionMode::getSelectionHandler()->rightButtonSelects() && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0 && e->buttons() == Qt::RightButton) { e->accept(); if (item != _rightClickedItem && item && _rightClickedItem) { _view->selectRegion(item, _rightClickedItem, _rightClickSelects); _rightClickedItem = item; _view->setCurrentKrViewItem(item); _contextMenuTimer.stop(); } return true; } return false; } bool KrMouseHandler::wheelEvent(QWheelEvent *e) { if (!_view->isFocused()) _view->op()->emitNeedFocus(); if (e->modifiers() == Qt::ControlModifier) { if (e->delta() > 0) { _view->zoomIn(); } else { _view->zoomOut(); } e->accept(); return true; } return false; } void KrMouseHandler::showContextMenu() { if (_rightClickedItem) _rightClickedItem->setSelected(true); if (_emptyContextMenu) _view->op()->emitEmptyContextMenu(_contextMenuPoint); else _view->op()->emitContextMenu(_contextMenuPoint); } void KrMouseHandler::handleContextMenu(KrViewItem * it, const QPoint & pos) { if (!_view->isFocused()) _view->op()->emitNeedFocus(); int i = KrSelectionMode::getSelectionHandler()->showContextMenu(); _contextMenuPoint = QPoint(pos.x(), pos.y() - _contextMenuShift); if (i < 0) { if (!it || it->isDummy()) _view->op()->emitEmptyContextMenu(_contextMenuPoint); else { _view->setCurrentKrViewItem(it); _view->op()->emitContextMenu(_contextMenuPoint); } } else if (i > 0) { _emptyContextMenu = !it || it->isDummy(); _contextMenuTimer.setSingleShot(true); _contextMenuTimer.start(i); } } void KrMouseHandler::otherEvent(QEvent * e) { switch (e->type()) { case QEvent::Timer: case QEvent::MouseMove: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: break; default: CANCEL_TWO_CLICK_RENAME; } } void KrMouseHandler::cancelTwoClickRename() { CANCEL_TWO_CLICK_RENAME; } bool KrMouseHandler::dragEnterEvent(QDragEnterEvent *e) { QList URLs = KUrlMimeData::urlsFromMimeData(e->mimeData()); e->setAccepted(!URLs.isEmpty()); return true; } bool KrMouseHandler::dragMoveEvent(QDragMoveEvent *e) { QList URLs = KUrlMimeData::urlsFromMimeData(e->mimeData()); e->setAccepted(!URLs.isEmpty()); return true; } bool KrMouseHandler::dragLeaveEvent(QDragLeaveEvent * /*e*/) { return false; } bool KrMouseHandler::dropEvent(QDropEvent *e) { _view->op()->emitGotDrop(e); return true; } diff --git a/krusader/Panel/krmousehandler.h b/krusader/Panel/PanelView/krmousehandler.h similarity index 100% rename from krusader/Panel/krmousehandler.h rename to krusader/Panel/PanelView/krmousehandler.h diff --git a/krusader/Panel/krselectionmode.cpp b/krusader/Panel/PanelView/krselectionmode.cpp similarity index 100% rename from krusader/Panel/krselectionmode.cpp rename to krusader/Panel/PanelView/krselectionmode.cpp diff --git a/krusader/Panel/krselectionmode.h b/krusader/Panel/PanelView/krselectionmode.h similarity index 100% rename from krusader/Panel/krselectionmode.h rename to krusader/Panel/PanelView/krselectionmode.h diff --git a/krusader/Panel/krsort.cpp b/krusader/Panel/PanelView/krsort.cpp similarity index 100% rename from krusader/Panel/krsort.cpp rename to krusader/Panel/PanelView/krsort.cpp diff --git a/krusader/Panel/krsort.h b/krusader/Panel/PanelView/krsort.h similarity index 98% rename from krusader/Panel/krsort.h rename to krusader/Panel/PanelView/krsort.h index c06f05f9..7dbfa34c 100644 --- a/krusader/Panel/krsort.h +++ b/krusader/Panel/PanelView/krsort.h @@ -1,124 +1,125 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef KRSORT_H #define KRSORT_H // QtCore #include #include #include class FileItem; class KrViewProperties; +/** Implements sorting for the panel list model. */ namespace KrSort { class SortProps { public: SortProps() {} SortProps(const SortProps& other) { init(other.fileitem(), other.column(), other.properties(), other.isDummy(), other.isAscending(), other.originalIndex(), other.customData()); } SortProps(FileItem *fileitem, int col, const KrViewProperties * props, bool isDummy, bool asc, int origNdx, QVariant customData) { init(fileitem, col, props, isDummy, asc, origNdx, customData); } inline int column() const { return _col; } inline const KrViewProperties * properties() const { return _prop; } inline bool isDummy() const { return _isdummy; } inline bool isAscending() const { return _ascending; } inline QString name() const { return _name; } inline QString extension() const { return _ext; } inline FileItem * fileitem() const { return _fileItem; } inline int originalIndex() const { return _index; } inline QString data() const { return _data; } inline const QVariant& customData() const { return _customData; } private: void init(FileItem *fileitem, int col, const KrViewProperties * props, bool isDummy, bool asc, int origNdx, QVariant customData); int _col; const KrViewProperties * _prop; bool _isdummy; FileItem * _fileItem; bool _ascending; QString _name; QString _ext; int _index; QString _data; QVariant _customData; }; bool compareTexts(QString aS1, QString aS2, const KrViewProperties * _viewProperties, bool asc, bool isName); bool itemLessThan(SortProps *sp, SortProps *sp2); bool itemGreaterThan(SortProps *sp, SortProps *sp2); bool compareTime(time_t time1, time_t time2, SortProps *sp, SortProps *sp2); typedef bool(*LessThanFunc)(SortProps*, SortProps*); class Sorter { public: Sorter(int reserveItems, const KrViewProperties *viewProperties, LessThanFunc lessThanFunc, LessThanFunc greaterThanFunc); Sorter(const Sorter &other); const QVector &items() const { return _items; } void sort(); void addItem(FileItem *fileitem, bool isDummy, int idx, QVariant customData); int insertIndex(FileItem *fileitem, bool isDummy, QVariant customData); private: bool descending() const; const KrViewProperties *_viewProperties; QVector _items; QVector _itemStore; LessThanFunc _lessThanFunc, _greaterThanFunc; }; } // namespace KrSort #endif // KRSORT_H diff --git a/krusader/Panel/krview.cpp b/krusader/Panel/PanelView/krview.cpp similarity index 99% rename from krusader/Panel/krview.cpp rename to krusader/Panel/PanelView/krview.cpp index ec4cd0f6..509d6dcd 100644 --- a/krusader/Panel/krview.cpp +++ b/krusader/Panel/PanelView/krview.cpp @@ -1,1209 +1,1209 @@ /*************************************************************************** krview.cpp ------------------- copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krview.h" -#include "viewactions.h" +#include "krselectionmode.h" #include "krviewfactory.h" #include "krviewitem.h" -#include "krselectionmode.h" -#include "krcolorcache.h" -#include "krpreviews.h" -#include "../kicons.h" -#include "../krglobal.h" -#include "../defaults.h" #include "../FileSystem/dirlisterinterface.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/krpermhandler.h" #include "../Filter/filterdialog.h" +#include "../defaults.h" +#include "../kicons.h" +#include "../krcolorcache.h" +#include "../krglobal.h" +#include "../krpreviews.h" +#include "../viewactions.h" // QtCore #include // QtGui #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #define FILEITEM getFileItem() KrView *KrViewOperator::_changedView = 0; KrViewProperties::PropertyType KrViewOperator::_changedProperties = KrViewProperties::NoProperty; // ----------------------------- operator KrViewOperator::KrViewOperator(KrView *view, QWidget *widget) : _view(view), _widget(widget), _massSelectionUpdate(false) { _saveDefaultSettingsTimer.setSingleShot(true); connect(&_saveDefaultSettingsTimer, SIGNAL(timeout()), SLOT(saveDefaultSettings())); } KrViewOperator::~KrViewOperator() { if(_changedView == _view) saveDefaultSettings(); } void KrViewOperator::startUpdate() { _view->refresh(); } void KrViewOperator::cleared() { _view->clear(); } void KrViewOperator::fileAdded(FileItem *fileitem) { _view->addItem(fileitem); } void KrViewOperator::fileUpdated(FileItem *newFileitem) { _view->updateItem(newFileitem); } void KrViewOperator::startDrag() { QStringList items; _view->getSelectedItems(&items); if (items.empty()) return ; // don't drag an empty thing QPixmap px; if (items.count() > 1 || _view->getCurrentKrViewItem() == 0) px = FL_LOADICON("queue"); // how much are we dragging else px = _view->getCurrentKrViewItem() ->icon(); emit letsDrag(items, px); } bool KrViewOperator::searchItem(const QString &text, bool caseSensitive, int direction) { KrViewItem * item = _view->getCurrentKrViewItem(); if (!item) { return false; } QRegExp rx(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); if (!direction) { if (rx.indexIn(item->name()) == 0) { return true; } direction = 1; } KrViewItem * startItem = item; while (true) { item = (direction > 0) ? _view->getNext(item) : _view->getPrev(item); if (!item) item = (direction > 0) ? _view->getFirst() : _view->getLast(); if (item == startItem) { return false; } if (rx.indexIn(item->name()) == 0) { _view->setCurrentKrViewItem(item); _view->makeItemVisible(item); return true; } } } bool KrViewOperator::filterSearch(const QString &text, bool caseSensitive) { _view->_quickFilterMask = QRegExp(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); _view->refresh(); return _view->_count || !_view->_files->numFileItems(); } void KrViewOperator::setMassSelectionUpdate(bool upd) { _massSelectionUpdate = upd; if (!upd) { emit selectionChanged(); _view->redraw(); } } void KrViewOperator::settingsChanged(KrViewProperties::PropertyType properties) { if(!_view->_updateDefaultSettings || _view->_ignoreSettingsChange) return; if(_changedView != _view) saveDefaultSettings(); _changedView = _view; _changedProperties = static_cast(_changedProperties | properties); _saveDefaultSettingsTimer.start(100); } void KrViewOperator::saveDefaultSettings() { _saveDefaultSettingsTimer.stop(); if(_changedView) _changedView->saveDefaultSettings(_changedProperties); _changedProperties = KrViewProperties::NoProperty; _changedView = 0; } // ----------------------------- krview const KrView::IconSizes KrView::iconSizes; KrView::KrView(KrViewInstance &instance, KConfig *cfg) : _config(cfg), _properties(0), _focused(false), _fileIconSize(0), _instance(instance), _files(0), _mainWindow(0), _widget(0), _nameToMakeCurrent(QString()), _previews(0), _updateDefaultSettings(false), _ignoreSettingsChange(false), _count(0), _numDirs(0), _dummyFileItem(0) { } KrView::~KrView() { _instance.m_objects.removeOne(this); delete _previews; _previews = 0; delete _dummyFileItem; _dummyFileItem = 0; if (_properties) qFatal("A class inheriting KrView didn't delete _properties!"); if (_operator) qFatal("A class inheriting KrView didn't delete _operator!"); } void KrView::init(bool enableUpdateDefaultSettings) { // sanity checks: if (!_widget) qFatal("_widget must be set during construction of KrView inheritors"); // ok, continue initProperties(); _operator = createOperator(); setup(); restoreDefaultSettings(); _updateDefaultSettings = enableUpdateDefaultSettings && KConfigGroup(_config, "Startup").readEntry("Update Default Panel Settings", _RememberPos); _instance.m_objects.append(this); } void KrView::initProperties() { const KConfigGroup grpInstance(_config, _instance.name()); const bool displayIcons = grpInstance.readEntry("With Icons", _WithIcons); const KConfigGroup grpSvr(_config, "Look&Feel"); const bool numericPermissions = grpSvr.readEntry("Numeric permissions", _NumericPermissions); int sortOps = 0; if (grpSvr.readEntry("Show Directories First", true)) sortOps |= KrViewProperties::DirsFirst; if(grpSvr.readEntry("Always sort dirs by name", false)) sortOps |= KrViewProperties::AlwaysSortDirsByName; if (!grpSvr.readEntry("Case Sensative Sort", _CaseSensativeSort)) sortOps |= KrViewProperties::IgnoreCase; if (grpSvr.readEntry("Locale Aware Sort", true)) sortOps |= KrViewProperties::LocaleAwareSort; KrViewProperties::SortOptions sortOptions = static_cast(sortOps); KrViewProperties::SortMethod sortMethod = static_cast( grpSvr.readEntry("Sort method", (int)_DefaultSortMethod)); const bool humanReadableSize = grpSvr.readEntry("Human Readable Size", _HumanReadableSize); // see KDE bug #40131 const bool localeAwareCompareIsCaseSensitive = QString("a").localeAwareCompare("B") > 0; QStringList defaultAtomicExtensions; defaultAtomicExtensions += ".tar.gz"; defaultAtomicExtensions += ".tar.bz2"; defaultAtomicExtensions += ".tar.lzma"; defaultAtomicExtensions += ".tar.xz"; defaultAtomicExtensions += ".moc.cpp"; QStringList atomicExtensions = grpSvr.readEntry("Atomic Extensions", defaultAtomicExtensions); for (QStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end();) { QString & ext = *i; ext = ext.trimmed(); if (!ext.length()) { i = atomicExtensions.erase(i); continue; } if (!ext.startsWith('.')) ext.insert(0, '.'); ++i; } _properties = new KrViewProperties(displayIcons, numericPermissions, sortOptions, sortMethod, humanReadableSize, localeAwareCompareIsCaseSensitive, atomicExtensions); } void KrView::showPreviews(bool show) { if(show) { if(!_previews) { _previews = new KrPreviews(this); _previews->update(); } } else { delete _previews; _previews = 0; } redraw(); // op()->settingsChanged(KrViewProperties::PropShowPreviews); op()->emitRefreshActions(); } void KrView::updatePreviews() { if(_previews) _previews->update(); } QPixmap KrView::processIcon(const QPixmap &icon, bool dim, const QColor & dimColor, int dimFactor, bool symlink) { QPixmap pixmap = icon; if (symlink) { const QStringList overlays = QStringList() << QString() << "emblem-symbolic-link"; KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop); } if(!dim) return pixmap; QImage dimmed = pixmap.toImage(); QPainter p(&dimmed); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(0, 0, icon.width(), icon.height(), dimColor); p.setCompositionMode(QPainter::CompositionMode_SourceOver); p.setOpacity((qreal)dimFactor / (qreal)100); p.drawPixmap(0, 0, icon.width(), icon.height(), pixmap); return QPixmap::fromImage(dimmed, Qt::ColorOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); } QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size/*, KRListItem::cmpColor color*/) { // KConfigGroup ag( krConfig, "Advanced"); ////////////////////////////// QPixmap icon; QString icon_name = fileitem->getIcon(); QString cacheName; if(!size) size = _FilelistIconSize.toInt(); QColor dimColor; int dimFactor; bool dim = !active && KrColorCache::getColorCache().getDimSettings(dimColor, dimFactor); if (icon_name.isNull()) icon_name = ""; cacheName.append(QString::number(size)); if(fileitem->isSymLink()) cacheName.append("LINK_"); if(dim) cacheName.append("DIM_"); cacheName.append(icon_name); //QPixmapCache::setCacheLimit( ag.readEntry("Icon Cache Size",_IconCacheSize) ); // first try the cache if (!QPixmapCache::find(cacheName, icon)) { icon = processIcon(krLoader->loadIcon(icon_name, KIconLoader::Desktop, size), dim, dimColor, dimFactor, fileitem->isSymLink()); // insert it into the cache QPixmapCache::insert(cacheName, icon); } return icon; } QPixmap KrView::getIcon(FileItem *fileitem) { if(_previews) { QPixmap icon; if(_previews->getPreview(fileitem, icon, _focused)) return icon; } return getIcon(fileitem, _focused, _fileIconSize); } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getItemsByMask(QString mask, QStringList* names, bool dirs, bool files) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if ((it->name() == "..") || !QDir::match(mask, it->name())) continue; // if we got here, than the item fits the mask if (it->getFileItem()->isDir() && !dirs) continue; // do we need to skip folders? if (!it->getFileItem()->isDir() && !files) continue; // do we need to skip files names->append(it->name()); } } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getSelectedItems(QStringList *names, bool fallbackToFocused) { for (KrViewItem *it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) names->append(it->name()); if (fallbackToFocused) { // if all else fails, take the current item const QString item = getCurrentItem(); if (names->empty() && !item.isEmpty() && item != "..") { names->append(item); } } } void KrView::getSelectedKrViewItems(KrViewItemList *items) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) items->append(it); // if all else fails, take the current item QString item = getCurrentItem(); if (items->empty() && !item.isEmpty() && item != ".." && getCurrentKrViewItem() != 0) { items->append(getCurrentKrViewItem()); } } QString KrView::statistics() { KIO::filesize_t size = calcSize(); KIO::filesize_t selectedSize = calcSelectedSize(); QString tmp; KConfigGroup grp(_config, "Look&Feel"); if(grp.readEntry("Show Size In Bytes", false)) { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize in Bytes, \ %5=filesize of all items in folder,%6=filesize in Bytes", "%1 out of %2, %3 (%4) out of %5 (%6)", numSelected(), _count, KIO::convertSize(selectedSize), KRpermHandler::parseSize(selectedSize), KIO::convertSize(size), KRpermHandler::parseSize(size)); } else { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize of all items in folder", "%1 out of %2, %3 out of %4", numSelected(), _count, KIO::convertSize(selectedSize), KIO::convertSize(size)); } // notify if we're running a filtered view if (filter() != KrViewProperties::All) tmp = ">> [ " + filterMask().nameFilter() + " ] " + tmp; return tmp; } bool KrView::changeSelection(const KRQuery& filter, bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); return changeSelection(filter, select, grpSvr.readEntry("Mark Dirs", _MarkDirs), true); } bool KrView::changeSelection(const KRQuery& filter, bool select, bool includeDirs, bool makeVisible) { if (op()) op()->setMassSelectionUpdate(true); KrViewItem *temp = getCurrentKrViewItem(); KrViewItem *firstMatch = 0; for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getFileItem()->isDir() && !includeDirs) continue; FileItem * file = it->getMutableFileItem(); // filter::match calls getMimetype which isn't const if (file == 0) continue; if (filter.match(file)) { it->setSelected(select); if (!firstMatch) firstMatch = it; } } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) { makeItemVisible(temp); } else if (makeVisible && firstMatch != 0) { // if no selected item is visible... KrViewItemList selectedItems; getSelectedKrViewItems(&selectedItems); bool anyVisible = false; for (KrViewItem *item : selectedItems) { if (isItemVisible(item)) { anyVisible = true; break; } } if (!anyVisible) { // ...scroll to fist selected item makeItemVisible(firstMatch); } } redraw(); return firstMatch != 0; // return if any file was selected } void KrView::invertSelection() { if (op()) op()->setMassSelectionUpdate(true); KConfigGroup grpSvr(_config, "Look&Feel"); bool markDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); KrViewItem *temp = getCurrentKrViewItem(); for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getFileItem()->isDir() && !markDirs && !it->isSelected()) continue; it->setSelected(!it->isSelected()); } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) makeItemVisible(temp); } QString KrView::firstUnmarkedBelowCurrent() { if (getCurrentKrViewItem() == 0) return QString(); KrViewItem * iterator = getNext(getCurrentKrViewItem()); while (iterator && iterator->isSelected()) iterator = getNext(iterator); if (!iterator) { iterator = getPrev(getCurrentKrViewItem()); while (iterator && iterator->isSelected()) iterator = getPrev(iterator); } if (!iterator) return QString(); return iterator->name(); } void KrView::delItem(const QString &name) { KrViewItem *it = findItemByName(name); if(!it) return; if(_previews) _previews->deletePreview(it); preDelItem(it); if (it->FILEITEM->isDir()) { --_numDirs; } --_count; delete it; op()->emitSelectionChanged(); } void KrView::addItem(FileItem *fileitem) { if (isFiltered(fileitem)) return; KrViewItem *item = preAddItem(fileitem); if (!item) return; // don't add it after all if(_previews) _previews->updatePreview(item); if (fileitem->isDir()) ++_numDirs; ++_count; if (item->name() == nameToMakeCurrent()) { setCurrentKrViewItem(item); // dictionary based - quick makeItemVisible(item); } op()->emitSelectionChanged(); } void KrView::updateItem(FileItem *newFileItem) { // file name did not change const QString name = newFileItem->getName(); // preserve 'current' and 'selection' const bool isCurrent = getCurrentItem() == name; QStringList selectedNames; getSelectedItems(&selectedNames, false); const bool isSelected = selectedNames.contains(name); // delete old file item delItem(name); if (!isFiltered(newFileItem)) { addItem(newFileItem); if(_previews) _previews->updatePreview(findItemByFileItem(newFileItem)); } if (isCurrent) setCurrentItem(name); if (isSelected) setSelected(newFileItem, true); op()->emitSelectionChanged(); } void KrView::clear() { if(_previews) _previews->clear(); _count = _numDirs = 0; delete _dummyFileItem; _dummyFileItem = 0; redraw(); } bool KrView::handleKeyEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Enter : case Qt::Key_Return : { if (e->modifiers() & Qt::ControlModifier) // let the panel handle it e->ignore(); else { KrViewItem * i = getCurrentKrViewItem(); if (i == 0) return true; QString tmp = i->name(); op()->emitExecuted(tmp); } return true; } case Qt::Key_QuoteLeft : // Terminal Emulator bugfix if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing op()->emitGoHome(); // ask krusader to move to the home directory } return true; case Qt::Key_Delete : // delete/trash the file op()->emitDefaultDeleteFiles(e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::ControlModifier); return true; case Qt::Key_Insert: { KrViewItem * i = getCurrentKrViewItem(); if (!i) return true; i->setSelected(!i->isSelected()); if (KrSelectionMode::getSelectionHandler()->insertMovesDown()) { KrViewItem * next = getNext(i); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); return true; } case Qt::Key_Space: { KrViewItem * viewItem = getCurrentKrViewItem(); if (viewItem != 0) { viewItem->setSelected(!viewItem->isSelected()); if (viewItem->getFileItem()->isDir() && KrSelectionMode::getSelectionHandler()->spaceCalculatesDiskSpace()) { op()->emitQuickCalcSpace(viewItem); } if (KrSelectionMode::getSelectionHandler()->spaceMovesDown()) { KrViewItem * next = getNext(viewItem); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); } return true; } case Qt::Key_Backspace : // Terminal Emulator bugfix case Qt::Key_Left : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing op()->emitDirUp(); // ask krusader to move up a directory } return true; // safety case Qt::Key_Right : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // just a normal click - do a lynx-like moving thing KrViewItem *i = getCurrentKrViewItem(); if (i) op()->emitGoInside(i->name()); } return true; case Qt::Key_Up : if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it - jump to the Location Bar e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getPrev(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Down : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { // let the panel handle it - jump to command line e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getNext(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Home: { if (e->modifiers() & Qt::ShiftModifier) { /* Shift+Home */ bool select = true; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getLast(); KrViewItem *item = getFirst(); op()->setMassSelectionUpdate(true); while (item) { item->setSelected(select); if (item == pos) select = false; item = getNext(item); } op()->setMassSelectionUpdate(false); } KrViewItem * first = getFirst(); if (first) { setCurrentKrViewItem(first); makeItemVisible(first); } } return true; case Qt::Key_End: if (e->modifiers() & Qt::ShiftModifier) { bool select = false; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getFirst(); op()->setMassSelectionUpdate(true); KrViewItem *item = getFirst(); while (item) { if (item == pos) select = true; item->setSelected(select); item = getNext(item); } op()->setMassSelectionUpdate(false); } else { KrViewItem *last = getLast(); if (last) { setCurrentKrViewItem(last); makeItemVisible(last); } } return true; case Qt::Key_PageDown: { KrViewItem * current = getCurrentKrViewItem(); int downStep = itemsPerPage(); while (downStep != 0 && current) { KrViewItem * newCurrent = getNext(current); if (newCurrent == 0) break; current = newCurrent; downStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_PageUp: { KrViewItem * current = getCurrentKrViewItem(); int upStep = itemsPerPage(); while (upStep != 0 && current) { KrViewItem * newCurrent = getPrev(current); if (newCurrent == 0) break; current = newCurrent; upStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_Escape: e->ignore(); return true; // otherwise the selection gets lost??!?? // also it is needed by the panel case Qt::Key_A : // mark all if (e->modifiers() == Qt::ControlModifier) { //FIXME: shouldn't there also be a shortcut for unselecting everything ? selectAllIncludingDirs(); return true; } // default continues here !!!!!!!!!!! default: return false; } return false; } void KrView::zoomIn() { int idx = iconSizes.indexOf(_fileIconSize); if(idx >= 0 && (idx+1) < iconSizes.count()) setFileIconSize(iconSizes[idx+1]); } void KrView::zoomOut() { int idx = iconSizes.indexOf(_fileIconSize); if(idx > 0) setFileIconSize(iconSizes[idx-1]); } void KrView::setFileIconSize(int size) { if(iconSizes.indexOf(size) < 0) return; _fileIconSize = size; if(_previews) { _previews->clear(); _previews->update(); } redraw(); op()->emitRefreshActions(); } int KrView::defaultFileIconSize() { KConfigGroup grpSvr(_config, _instance.name()); return grpSvr.readEntry("IconSize", _FilelistIconSize).toInt(); } void KrView::saveDefaultSettings(KrViewProperties::PropertyType properties) { saveSettings(KConfigGroup(_config, _instance.name()), properties); op()->emitRefreshActions(); } void KrView::restoreDefaultSettings() { restoreSettings(KConfigGroup(_config, _instance.name())); } void KrView::saveSettings(KConfigGroup group, KrViewProperties::PropertyType properties) { if(properties & KrViewProperties::PropIconSize) group.writeEntry("IconSize", fileIconSize()); if(properties & KrViewProperties::PropShowPreviews) group.writeEntry("ShowPreviews", previewsShown()); if(properties & KrViewProperties::PropSortMode) saveSortMode(group); if(properties & KrViewProperties::PropFilter) { group.writeEntry("Filter", static_cast(_properties->filter)); group.writeEntry("FilterApplysToDirs", _properties->filterApplysToDirs); if(_properties->filterSettings.isValid()) _properties->filterSettings.save(KConfigGroup(&group, "FilterSettings")); } } void KrView::restoreSettings(KConfigGroup group) { _ignoreSettingsChange = true; doRestoreSettings(group); _ignoreSettingsChange = false; refresh(); } void KrView::doRestoreSettings(KConfigGroup group) { restoreSortMode(group); setFileIconSize(group.readEntry("IconSize", defaultFileIconSize())); showPreviews(group.readEntry("ShowPreviews", false)); _properties->filter = static_cast(group.readEntry("Filter", static_cast(KrViewProperties::All))); _properties->filterApplysToDirs = group.readEntry("FilterApplysToDirs", false); _properties->filterSettings.load(KConfigGroup(&group, "FilterSettings")); _properties->filterMask = _properties->filterSettings.toQuery(); } void KrView::applySettingsToOthers() { for(int i = 0; i < _instance.m_objects.length(); i++) { KrView *view = _instance.m_objects[i]; if(this != view) { view->_ignoreSettingsChange = true; view->copySettingsFrom(this); view->_ignoreSettingsChange = false; } } } void KrView::sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending) { if(sortColumn == _properties->sortColumn && descending == (bool) (_properties->sortOptions & KrViewProperties::Descending)) return; int options = _properties->sortOptions; if(descending) options |= KrViewProperties::Descending; else options &= ~KrViewProperties::Descending; _properties->sortColumn = sortColumn; _properties->sortOptions = static_cast(options); // op()->settingsChanged(KrViewProperties::PropSortMode); } bool KrView::drawCurrent() const { return isFocused() || KConfigGroup(_config, "Look&Feel") .readEntry("Always Show Current Item", _AlwaysShowCurrentItem); } void KrView::saveSortMode(KConfigGroup &group) { group.writeEntry("Sort Column", static_cast(_properties->sortColumn)); group.writeEntry("Descending Sort Order", _properties->sortOptions & KrViewProperties::Descending); } void KrView::restoreSortMode(KConfigGroup &group) { int column = group.readEntry("Sort Column", static_cast(KrViewProperties::Name)); bool isDescending = group.readEntry("Descending Sort Order", false); setSortMode(static_cast(column), isDescending); } QString KrView::krPermissionText(const FileItem * fileitem) { QString tmp; switch (fileitem->isReadable()) { case ALLOWED_PERM: tmp+='r'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (fileitem->isWriteable()) { case ALLOWED_PERM: tmp+='w'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (fileitem->isExecutable()) { case ALLOWED_PERM: tmp+='x'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } return tmp; } QString KrView::permissionsText(const KrViewProperties *properties, const FileItem *fileItem) { return properties->numericPermissions ? QString().asprintf("%.4o", fileItem->getMode() & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)) : fileItem->getPerm(); } QString KrView::sizeText(const KrViewProperties *properties, KIO::filesize_t size) { return properties->humanReadableSize ? KIO::convertSize(size) : KRpermHandler::parseSize(size); } QString KrView::mimeTypeText(FileItem *fileItem) { QMimeType mt = QMimeDatabase().mimeTypeForName(fileItem->getMime()); return mt.isValid() ? mt.comment() : QString(); } bool KrView::isFiltered(FileItem *fileitem) { if (_quickFilterMask.isValid() && _quickFilterMask.indexIn(fileitem->getName()) == -1) return true; bool filteredOut = false; bool isDir = fileitem->isDir(); if (!isDir || (isDir && properties()->filterApplysToDirs)) { switch (properties()->filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : if (!properties()->filterMask.match(fileitem)) filteredOut = true; break; case KrViewProperties::Dirs: if (!isDir) filteredOut = true; break; case KrViewProperties::Files: if (isDir) filteredOut = true; break; default: break; } } return filteredOut; } void KrView::setFiles(DirListerInterface *files) { if(files != _files) { clear(); if(_files) QObject::disconnect(_files, 0, op(), 0); _files = files; } if(!_files) return; QObject::disconnect(_files, 0, op(), 0); QObject::connect(_files, &DirListerInterface::scanDone, op(), &KrViewOperator::startUpdate); QObject::connect(_files, &DirListerInterface::cleared, op(), &KrViewOperator::cleared); QObject::connect(_files, &DirListerInterface::addedFileItem, op(), &KrViewOperator::fileAdded); QObject::connect(_files, &DirListerInterface::updatedFileItem, op(), &KrViewOperator::fileUpdated); } void KrView::setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter, bool applyToDirs) { _properties->filter = filter; _properties->filterSettings = customFilter; _properties->filterMask = customFilter.toQuery(); _properties->filterApplysToDirs = applyToDirs; refresh(); } void KrView::setFilter(KrViewProperties::FilterSpec filter) { KConfigGroup cfg(_config, "Look&Feel"); bool rememberSettings = cfg.readEntry("FilterDialogRemembersSettings", _FilterDialogRemembersSettings); bool applyToDirs = rememberSettings ? _properties->filterApplysToDirs : false; switch (filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : { FilterDialog dialog(_widget, i18n("Filter Files"), QStringList(i18n("Apply filter to folders")), false); dialog.checkExtraOption(i18n("Apply filter to folders"), applyToDirs); if(rememberSettings) dialog.applySettings(_properties->filterSettings); dialog.exec(); FilterSettings s(dialog.getSettings()); if(!s.isValid()) // if the user canceled - quit return; _properties->filterSettings = s; _properties->filterMask = s.toQuery(); applyToDirs = dialog.isExtraOptionChecked(i18n("Apply filter to folders")); } break; default: return; } _properties->filterApplysToDirs = applyToDirs; _properties->filter = filter; refresh(); } void KrView::customSelection(bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); bool includeDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); FilterDialog dialog(0, i18n("Select Files"), QStringList(i18n("Apply selection to folders")), false); dialog.checkExtraOption(i18n("Apply selection to folders"), includeDirs); dialog.exec(); KRQuery query = dialog.getQuery(); // if the user canceled - quit if (query.isNull()) return ; includeDirs = dialog.isExtraOptionChecked(i18n("Apply selection to folders")); changeSelection(query, select, includeDirs); } void KrView::refresh() { QString currentItem = getCurrentItem(); QList selection = selectedUrls(); QModelIndex currentIndex = getCurrentIndex(); clear(); if(!_files) return; QList fileItems; // if we are not at the root add the ".." entry if(!_files->isRoot()) { _dummyFileItem = FileItem::createDummy(); fileItems << _dummyFileItem; } foreach(FileItem *fileitem, _files->fileItems()) { if(!fileitem || isFiltered(fileitem)) continue; if(fileitem->isDir()) _numDirs++; _count++; fileItems << fileitem; } populate(fileItems, _dummyFileItem); if(!selection.isEmpty()) setSelectionUrls(selection); if (!nameToMakeCurrent().isEmpty()) { setCurrentItem(nameToMakeCurrent()); setNameToMakeCurrent(""); } else if (!currentItem.isEmpty()) { if (currentItem == ".." && _count > 0 && !_quickFilterMask.isEmpty() && _quickFilterMask.isValid()) { // In a filtered view we should never select the dummy entry if // there are real matches. setCurrentKrViewItem(getNext(getFirst())); } else setCurrentItem(currentItem, currentIndex); } else { setCurrentKrViewItem(getFirst()); } updatePreviews(); redraw(); op()->emitSelectionChanged(); } void KrView::setSelected(const FileItem* fileitem, bool select) { if (fileitem == _dummyFileItem) return; if (select) clearSavedSelection(); intSetSelected(fileitem, select); } void KrView::saveSelection() { _savedSelection = selectedUrls(); op()->emitRefreshActions(); } void KrView::restoreSelection() { if(canRestoreSelection()) setSelectionUrls(_savedSelection); } void KrView::clearSavedSelection() { _savedSelection.clear(); op()->emitRefreshActions(); } void KrView::markSameBaseName() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("%1.*").arg(item->name(false))); changeSelection(query, true, false); } void KrView::markSameExtension() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("*.%1").arg(item->extension())); changeSelection(query, true, false); } diff --git a/krusader/Panel/krview.h b/krusader/Panel/PanelView/krview.h similarity index 100% rename from krusader/Panel/krview.h rename to krusader/Panel/PanelView/krview.h diff --git a/krusader/Panel/krviewfactory.cpp b/krusader/Panel/PanelView/krviewfactory.cpp similarity index 100% rename from krusader/Panel/krviewfactory.cpp rename to krusader/Panel/PanelView/krviewfactory.cpp diff --git a/krusader/Panel/krviewfactory.h b/krusader/Panel/PanelView/krviewfactory.h similarity index 100% rename from krusader/Panel/krviewfactory.h rename to krusader/Panel/PanelView/krviewfactory.h diff --git a/krusader/Panel/krviewitem.cpp b/krusader/Panel/PanelView/krviewitem.cpp similarity index 100% rename from krusader/Panel/krviewitem.cpp rename to krusader/Panel/PanelView/krviewitem.cpp diff --git a/krusader/Panel/krviewitem.h b/krusader/Panel/PanelView/krviewitem.h similarity index 100% rename from krusader/Panel/krviewitem.h rename to krusader/Panel/PanelView/krviewitem.h diff --git a/krusader/Panel/krviewitemdelegate.cpp b/krusader/Panel/PanelView/krviewitemdelegate.cpp similarity index 99% rename from krusader/Panel/krviewitemdelegate.cpp rename to krusader/Panel/PanelView/krviewitemdelegate.cpp index 46a45afb..0d8b554b 100644 --- a/krusader/Panel/krviewitemdelegate.cpp +++ b/krusader/Panel/PanelView/krviewitemdelegate.cpp @@ -1,151 +1,151 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krviewitemdelegate.h" #include "krviewproperties.h" #include "../krglobal.h" -#include "listpanel.h" +#include "../listpanel.h" // QtGui #include #include // QtWidgets #include #include #include #include KrViewItemDelegate::KrViewItemDelegate(QObject *parent) : QItemDelegate(parent), _currentlyEdited(-1), _dontDraw(false) {} void KrViewItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem opt = option; opt.state &= ~QStyle::State_Selected; _dontDraw = (_currentlyEdited == index.row()) && (index.column() == KrViewProperties::Ext); QItemDelegate::paint(painter, opt, index); } void KrViewItemDelegate::drawDisplay(QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QString & text) const { if (!_dontDraw) QItemDelegate::drawDisplay(painter, option, rect, text); } QWidget * KrViewItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &sovi, const QModelIndex &index) const { _currentlyEdited = index.row(); return QItemDelegate::createEditor(parent, sovi, index); } void KrViewItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QItemDelegate::setEditorData(editor, index); QLineEdit *lineEdit = qobject_cast (editor); if (lineEdit) { KConfigGroup gl(krConfig, "Look&Feel"); QFont font = index.data(Qt::FontRole).value(); lineEdit->setFont(font); if (gl.readEntry("Rename Selects Extension", true)) lineEdit->selectAll(); else { QString nameWithoutExt = index.data(Qt::UserRole).toString(); lineEdit->deselect(); lineEdit->setSelection(0, nameWithoutExt.length()); } } } QSize KrViewItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const { QSize size = QItemDelegate::sizeHint(option, index); if (size.isEmpty()) { // prevent items without text from bloating the view vertically return QSize(0, 0); } return size; } bool KrViewItemDelegate::eventFilter(QObject *object, QEvent *event) { QWidget *editor = qobject_cast(object); if (!editor) return false; if (event->type() == QEvent::KeyPress) { switch (static_cast(event)->key()) { case Qt::Key_Tab: case Qt::Key_Backtab: _currentlyEdited = -1; emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache); return true; case Qt::Key_Enter: case Qt::Key_Return: if (QLineEdit *e = qobject_cast(editor)) { if (!e->hasAcceptableInput()) return true; event->accept(); emit commitData(editor); emit closeEditor(editor, QAbstractItemDelegate::SubmitModelCache); _currentlyEdited = -1; return true; } return false; case Qt::Key_Escape: event->accept(); // don't commit data _currentlyEdited = -1; emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache); break; default: return false; } if (editor->parentWidget()) editor->parentWidget()->setFocus(); return true; } else if (event->type() == QEvent::FocusOut) { if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) { QWidget *w = QApplication::focusWidget(); while (w) { // don't worry about focus changes internally in the editor if (w == editor) return false; w = w->parentWidget(); } // Opening a modal dialog will start a new eventloop // that will process the deleteLater event. if (QApplication::activeModalWidget() && !QApplication::activeModalWidget()->isAncestorOf(editor) && qobject_cast(QApplication::activeModalWidget())) return false; _currentlyEdited = -1; // manually set focus back to panel after rename canceled by focusing another window ACTIVE_PANEL->gui->slotFocusOnMe(); emit closeEditor(editor, RevertModelCache); } } else if (event->type() == QEvent::ShortcutOverride) { const QKeyEvent *ke = static_cast(event); if (ke->key() == Qt::Key_Escape || (ke->key() == Qt::Key_Backspace && ke->modifiers() == Qt::ControlModifier)) { event->accept(); return true; } } return false; } diff --git a/krusader/Panel/krviewitemdelegate.h b/krusader/Panel/PanelView/krviewitemdelegate.h similarity index 100% rename from krusader/Panel/krviewitemdelegate.h rename to krusader/Panel/PanelView/krviewitemdelegate.h diff --git a/krusader/Panel/krviewproperties.cpp b/krusader/Panel/PanelView/krviewproperties.cpp similarity index 100% rename from krusader/Panel/krviewproperties.cpp rename to krusader/Panel/PanelView/krviewproperties.cpp diff --git a/krusader/Panel/krviewproperties.h b/krusader/Panel/PanelView/krviewproperties.h similarity index 100% rename from krusader/Panel/krviewproperties.h rename to krusader/Panel/PanelView/krviewproperties.h diff --git a/krusader/Panel/listmodel.cpp b/krusader/Panel/PanelView/listmodel.cpp similarity index 99% rename from krusader/Panel/listmodel.cpp rename to krusader/Panel/PanelView/listmodel.cpp index 9c705c0d..057298e4 100644 --- a/krusader/Panel/listmodel.cpp +++ b/krusader/Panel/PanelView/listmodel.cpp @@ -1,549 +1,548 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "listmodel.h" -#include "krcolorcache.h" #include "krinterview.h" -#include "krpanel.h" #include "krviewproperties.h" - +#include "../FileSystem/fileitem.h" #include "../defaults.h" +#include "../krcolorcache.h" #include "../krglobal.h" -#include "../FileSystem/fileitem.h" +#include "../krpanel.h" #include #include ListModel::ListModel(KrInterView *view) : QAbstractListModel(0), _extensionEnabled(true), _view(view), _dummyFileItem(0), _ready(false), _justForSizeHint(false), _alternatingTable(false) { KConfigGroup grpSvr(krConfig, "Look&Feel"); _defaultFont = grpSvr.readEntry("Filelist Font", _FilelistFont); } void ListModel::populate(const QList &files, FileItem *dummy) { _fileItems = files; _dummyFileItem = dummy; _ready = true; if(lastSortOrder() != KrViewProperties::NoColumn) sort(); else { emit layoutAboutToBeChanged(); for(int i = 0; i < _fileItems.count(); i++) { updateIndices(_fileItems[i], i); } emit layoutChanged(); } } ListModel::~ListModel() { } void ListModel::clear(bool emitLayoutChanged) { if(!_fileItems.count()) return; emit layoutAboutToBeChanged(); // clear persistent indexes QModelIndexList oldPersistentList = persistentIndexList(); QModelIndexList newPersistentList; newPersistentList.reserve(oldPersistentList.size()); for (int i=0; i< oldPersistentList.size(); ++i) newPersistentList.append(QModelIndex()); changePersistentIndexList(oldPersistentList, newPersistentList); _fileItems.clear(); _fileItemNdx.clear(); _nameNdx.clear(); _urlNdx.clear(); _dummyFileItem = 0; if (emitLayoutChanged) emit layoutChanged(); } int ListModel::rowCount(const QModelIndex& /*parent*/) const { return _fileItems.count(); } int ListModel::columnCount(const QModelIndex& /*parent*/) const { return KrViewProperties::MAX_COLUMNS; } QVariant ListModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || index.row() >= rowCount()) return QVariant(); FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == 0) return QVariant(); switch (role) { case Qt::FontRole: return _defaultFont; case Qt::EditRole: { if (index.column() == 0) { return fileitem->getName(); } return QVariant(); } case Qt::UserRole: { if (index.column() == 0) { return nameWithoutExtension(fileitem, false); } return QVariant(); } case Qt::ToolTipRole: { if (index.column() == KrViewProperties::Name) { return fileitem == _dummyFileItem ? QVariant() : toolTipText(fileitem); } // breaktrough } case Qt::DisplayRole: { switch (index.column()) { case KrViewProperties::Name: { return nameWithoutExtension(fileitem); } case KrViewProperties::Ext: { QString nameOnly = nameWithoutExtension(fileitem); const QString& fileitemName = fileitem->getName(); return fileitemName.mid(nameOnly.length() + 1); } case KrViewProperties::Size: { if (fileitem->getUISize() == (KIO::filesize_t)-1) { //HACK add <> brackets AFTER translating - otherwise KUIT thinks it's a tag static QString label = QString("<") + i18nc("Show the string 'DIR' instead of file size in detailed view (for folders)", "DIR") + '>'; return label; } else return KrView::sizeText(properties(), fileitem->getUISize()); } case KrViewProperties::Type: { if (fileitem == _dummyFileItem) return QVariant(); const QString mimeType = KrView::mimeTypeText(fileitem); return mimeType.isEmpty() ? QVariant() : mimeType; } case KrViewProperties::Modified: { return fileitem == _dummyFileItem ? QVariant() : dateText(fileitem->getTime_t()); } case KrViewProperties::Changed: { return fileitem == _dummyFileItem ? QVariant() : dateText(fileitem->getChangedTime()); } case KrViewProperties::Accessed: { return fileitem == _dummyFileItem ? QVariant() : dateText(fileitem->getAccessTime()); } case KrViewProperties::Permissions: { if (fileitem == _dummyFileItem) return QVariant(); return KrView::permissionsText(properties(), fileitem); } case KrViewProperties::KrPermissions: { if (fileitem == _dummyFileItem) return QVariant(); return KrView::krPermissionText(fileitem); } case KrViewProperties::Owner: { if (fileitem == _dummyFileItem) return QVariant(); return fileitem->getOwner(); } case KrViewProperties::Group: { if (fileitem == _dummyFileItem) return QVariant(); return fileitem->getGroup(); } default: return QString(); } return QVariant(); } case Qt::DecorationRole: { switch (index.column()) { case KrViewProperties::Name: { if (properties()->displayIcons) { if (_justForSizeHint) return QPixmap(_view->fileIconSize(), _view->fileIconSize()); return _view->getIcon(fileitem); } break; } default: break; } return QVariant(); } case Qt::TextAlignmentRole: { switch (index.column()) { case KrViewProperties::Size: return QVariant(Qt::AlignRight | Qt::AlignVCenter); default: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); } return QVariant(); } case Qt::BackgroundRole: case Qt::ForegroundRole: { KrColorItemType colorItemType; colorItemType.m_activePanel = _view->isFocused(); int actRow = index.row(); if (_alternatingTable) { int itemNum = _view->itemsPerPage(); if (itemNum == 0) itemNum++; if ((itemNum & 1) == 0) actRow += (actRow / itemNum); } colorItemType.m_alternateBackgroundColor = (actRow & 1); colorItemType.m_currentItem = _view->getCurrentIndex().row() == index.row(); colorItemType.m_selectedItem = _view->isSelected(index); if (fileitem->isSymLink()) { if (fileitem->isBrokenLink()) colorItemType.m_fileType = KrColorItemType::InvalidSymlink; else colorItemType.m_fileType = KrColorItemType::Symlink; } else if (fileitem->isDir()) colorItemType.m_fileType = KrColorItemType::Directory; else if (fileitem->isExecutable()) colorItemType.m_fileType = KrColorItemType::Executable; else colorItemType.m_fileType = KrColorItemType::File; KrColorGroup cols; KrColorCache::getColorCache().getColors(cols, colorItemType); if (colorItemType.m_selectedItem) { if (role == Qt::ForegroundRole) return cols.highlightedText(); else return cols.highlight(); } if (role == Qt::ForegroundRole) return cols.text(); else return cols.background(); } default: return QVariant(); } } bool ListModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (role == Qt::EditRole && index.isValid()) { if (index.row() < rowCount() && index.row() >= 0) { FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == 0) return false; _view->op()->emitRenameItem(fileitem->getName(), value.toString()); } } if (role == Qt::UserRole && index.isValid()) { _justForSizeHint = value.toBool(); } return QAbstractListModel::setData(index, value, role); } void ListModel::sort(int column, Qt::SortOrder order) { _view->sortModeUpdated(column, order); if(lastSortOrder() == KrViewProperties::NoColumn) return; emit layoutAboutToBeChanged(); QModelIndexList oldPersistentList = persistentIndexList(); KrSort::Sorter sorter(createSorter()); sorter.sort(); _fileItems.clear(); _fileItemNdx.clear(); _nameNdx.clear(); _urlNdx.clear(); bool sortOrderChanged = false; QHash changeMap; for (int i = 0; i < sorter.items().count(); ++i) { const KrSort::SortProps *props = sorter.items()[i]; _fileItems.append(props->fileitem()); changeMap[ props->originalIndex() ] = i; if (i != props->originalIndex()) sortOrderChanged = true; updateIndices(props->fileitem(), i); } QModelIndexList newPersistentList; foreach(const QModelIndex &mndx, oldPersistentList) newPersistentList << index(changeMap[ mndx.row()], mndx.column()); changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); if (sortOrderChanged) _view->makeItemVisible(_view->getCurrentKrViewItem()); } QModelIndex ListModel::addItem(FileItem *fileitem) { emit layoutAboutToBeChanged(); if(lastSortOrder() == KrViewProperties::NoColumn) { int idx = _fileItems.count(); _fileItems.append(fileitem); updateIndices(fileitem, idx); emit layoutChanged(); return index(idx, 0); } QModelIndexList oldPersistentList = persistentIndexList(); KrSort::Sorter sorter(createSorter()); int insertIndex = sorter.insertIndex(fileitem, fileitem == _dummyFileItem, customSortData(fileitem)); if (insertIndex != _fileItems.count()) _fileItems.insert(insertIndex, fileitem); else _fileItems.append(fileitem); for (int i = insertIndex; i < _fileItems.count(); ++i) { updateIndices(_fileItems[i], i); } QModelIndexList newPersistentList; foreach(const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); if (newRow >= insertIndex) newRow++; newPersistentList << index(newRow, mndx.column()); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); _view->makeItemVisible(_view->getCurrentKrViewItem()); return index(insertIndex, 0); } QModelIndex ListModel::removeItem(FileItem *fileitem) { QModelIndex currIndex = _view->getCurrentIndex(); int removeIdx = _fileItems.indexOf(fileitem); if(removeIdx < 0) return currIndex; emit layoutAboutToBeChanged(); QModelIndexList oldPersistentList = persistentIndexList(); QModelIndexList newPersistentList; _fileItems.removeAt(removeIdx); if (currIndex.row() == removeIdx) { if (_fileItems.count() == 0) currIndex = QModelIndex(); else if (removeIdx >= _fileItems.count()) currIndex = index(_fileItems.count() - 1, 0); else currIndex = index(removeIdx, 0); } else if (currIndex.row() > removeIdx) { currIndex = index(currIndex.row() - 1, 0); } _fileItemNdx.remove(fileitem); _nameNdx.remove(fileitem->getName()); _urlNdx.remove(fileitem->getUrl()); // update indices for fileItems following fileitem for (int i = removeIdx; i < _fileItems.count(); i++) { updateIndices(_fileItems[i], i); } foreach(const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); if (newRow > removeIdx) newRow--; if (newRow != removeIdx) newPersistentList << index(newRow, mndx.column()); else newPersistentList << QModelIndex(); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); _view->makeItemVisible(_view->getCurrentKrViewItem()); return currIndex; } QVariant ListModel::headerData(int section, Qt::Orientation orientation, int role) const { // ignore anything that's not display, and not horizontal if (role != Qt::DisplayRole || orientation != Qt::Horizontal) return QVariant(); switch (section) { case KrViewProperties::Name: return i18nc("File property", "Name"); case KrViewProperties::Ext: return i18nc("File property", "Ext"); case KrViewProperties::Size: return i18nc("File property", "Size"); case KrViewProperties::Type: return i18nc("File property", "Type"); case KrViewProperties::Modified: return i18nc("File property", "Modified"); case KrViewProperties::Changed: return i18nc("File property", "Changed"); case KrViewProperties::Accessed: return i18nc("File property", "Accessed"); case KrViewProperties::Permissions: return i18nc("File property", "Perms"); case KrViewProperties::KrPermissions: return i18nc("File property", "rwx"); case KrViewProperties::Owner: return i18nc("File property", "Owner"); case KrViewProperties::Group: return i18nc("File property", "Group"); } return QString(); } const KrViewProperties *ListModel::properties() const { return _view->properties(); } FileItem *ListModel::fileItemAt(const QModelIndex &index) { if (!index.isValid() || index.row() < 0 || index.row() >= _fileItems.count()) return 0; return _fileItems[ index.row()]; } const QModelIndex & ListModel::fileItemIndex(const FileItem *fileitem) { return _fileItemNdx[ (FileItem *) fileitem ]; } const QModelIndex & ListModel::nameIndex(const QString & st) { return _nameNdx[ st ]; } Qt::ItemFlags ListModel::flags(const QModelIndex & index) const { Qt::ItemFlags flags = QAbstractListModel::flags(index); if (!index.isValid()) return flags; if (index.row() >= rowCount()) return flags; FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == _dummyFileItem) { flags = (flags & (~Qt::ItemIsSelectable)) | Qt::ItemIsDropEnabled; } else flags = flags | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; return flags; } Qt::SortOrder ListModel::lastSortDir() const { return (properties()->sortOptions & KrViewProperties::Descending) ? Qt::DescendingOrder : Qt::AscendingOrder; } int ListModel::lastSortOrder() const { return properties()->sortColumn; } QString ListModel::nameWithoutExtension(const FileItem *fileItem, bool checkEnabled) const { if ((checkEnabled && !_extensionEnabled) || fileItem->isDir()) return fileItem->getName(); // check if the file has an extension const QString& fileItemName = fileItem->getName(); int loc = fileItemName.lastIndexOf('.'); // avoid mishandling of .bashrc and friend // and virtfs / search result names like "/dir/.file" which whould become "/dir/" if (loc > 0 && fileItemName.lastIndexOf('/') < loc) { // check if it has one of the predefined 'atomic extensions' for (QStringList::const_iterator i = properties()->atomicExtensions.begin(); i != properties()->atomicExtensions.end(); ++i) { if (fileItemName.endsWith(*i) && fileItemName != *i) { loc = fileItemName.length() - (*i).length(); break; } } } else return fileItemName; return fileItemName.left(loc); } const QModelIndex &ListModel::indexFromUrl(const QUrl &url) { return _urlNdx[url]; } KrSort::Sorter ListModel::createSorter() { KrSort::Sorter sorter(_fileItems.count(), properties(), lessThanFunc(), greaterThanFunc()); for(int i = 0; i < _fileItems.count(); i++) sorter.addItem(_fileItems[i], _fileItems[i] == _dummyFileItem, i, customSortData(_fileItems[i])); return sorter; } void ListModel::updateIndices(FileItem *file, int i) { _fileItemNdx[file] = index(i, 0); _nameNdx[file->getName()] = index(i, 0); _urlNdx[file->getUrl()] = index(i, 0); } QString ListModel::toolTipText(FileItem *fileItem) const { //"

"; // disable automatic word-wrap QString text = "" + fileItem->getName() + "


"; if (fileItem->getUISize() != (KIO::filesize_t)-1) { const QString size = KrView::sizeText(properties(), fileItem->getUISize()); text += i18n("Size: %1", size) + "
"; } text += i18nc("File property", "Type: %1", KrView::mimeTypeText(fileItem)); text += "
" + i18nc("File property", "Modified: %1", dateText(fileItem->getTime_t())); text += "
" + i18nc("File property", "Changed: %1", dateText(fileItem->getChangedTime())); text += "
" + i18nc("File property", "Last Access: %1", dateText(fileItem->getAccessTime())); text += "
" + i18nc("File property", "Permissions: %1", KrView::permissionsText(properties(), fileItem)); text += "
" + i18nc("File property", "Owner: %1", fileItem->getOwner()); text += "
" + i18nc("File property", "Group: %1", fileItem->getGroup()); if (fileItem->isSymLink()) { KLocalizedString ls; if (fileItem->isBrokenLink()) ls = ki18nc("File property; broken symbolic link", "Link to: %1 - (broken)"); else ls = ki18nc("File property", "Link to: %1"); text += "
" + ls.subs(fileItem->getSymDest()).toString(); } return text; } QString ListModel::dateText(time_t time) { struct tm* t = localtime((time_t *) & time); const QDateTime dateTime(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), QTime(t->tm_hour, t->tm_min)); return QLocale().toString(dateTime, QLocale::ShortFormat); } diff --git a/krusader/Panel/listmodel.h b/krusader/Panel/PanelView/listmodel.h similarity index 99% rename from krusader/Panel/listmodel.h rename to krusader/Panel/PanelView/listmodel.h index 938d3d58..6dd3dc1f 100644 --- a/krusader/Panel/listmodel.h +++ b/krusader/Panel/PanelView/listmodel.h @@ -1,120 +1,119 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef LISTMODEL_H #define LISTMODEL_H // QtCore #include // QtGui #include #include "krsort.h" - class FileItem; class KrInterView; class KrViewProperties; /** * @brief The list model for all panel views. */ class ListModel: public QAbstractListModel { Q_OBJECT public: explicit ListModel(KrInterView *); virtual ~ListModel(); inline bool ready() const { return _ready; } void populate(const QList &files, FileItem *dummy); QModelIndex addItem(FileItem *); QModelIndex removeItem(FileItem *); int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) Q_DECL_OVERRIDE; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; void setExtensionEnabled(bool exten) { _extensionEnabled = exten; } const KrViewProperties * properties() const; void sort() { sort(lastSortOrder(), lastSortDir()); } void clear(bool emitLayoutChanged = true); QList fileItems() { return _fileItems; } FileItem * fileItemAt(const QModelIndex &index); FileItem *dummyFileItem() const { return _dummyFileItem; } const QModelIndex & fileItemIndex(const FileItem *); const QModelIndex & nameIndex(const QString &); const QModelIndex & indexFromUrl(const QUrl &url); virtual Qt::ItemFlags flags(const QModelIndex & index) const Q_DECL_OVERRIDE; void emitChanged() { emit layoutChanged(); } Qt::SortOrder lastSortDir() const; int lastSortOrder() const; void setAlternatingTable(bool altTable) { _alternatingTable = altTable; } public slots: virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) Q_DECL_OVERRIDE; protected: KrSort::LessThanFunc lessThanFunc() { return KrSort::itemLessThan; } KrSort::LessThanFunc greaterThanFunc() const { return KrSort::itemGreaterThan; } QVariant customSortData(FileItem *) const { return QVariant(); } KrSort::Sorter createSorter(); QString nameWithoutExtension(const FileItem * fileitem, bool checkEnabled = true) const; private: void updateIndices(FileItem *file, int index); QString toolTipText(FileItem *fileItem) const; static QString dateText(time_t time); QList _fileItems; QHash _fileItemNdx; QHash _nameNdx; QHash _urlNdx; bool _extensionEnabled; KrInterView * _view; FileItem * _dummyFileItem; bool _ready; QFont _defaultFont; bool _justForSizeHint; bool _alternatingTable; }; #endif // __listmodel__ diff --git a/krusader/Panel/dirhistoryqueue.cpp b/krusader/Panel/dirhistoryqueue.cpp index 6e0ac190..afd3e841 100644 --- a/krusader/Panel/dirhistoryqueue.cpp +++ b/krusader/Panel/dirhistoryqueue.cpp @@ -1,160 +1,160 @@ /***************************************************************************** * Copyright (C) 2004 Shie Erlich * * Copyright (C) 2004 Rafi Yanai * * Copyright (C) 2010 Jan Lepper * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "dirhistoryqueue.h" #include "krpanel.h" -#include "krview.h" +#include "PanelView/krview.h" #include "../defaults.h" #include "../krservices.h" // QtCore #include DirHistoryQueue::DirHistoryQueue(KrPanel *panel) : _panel(panel), _currentPos(0) { } DirHistoryQueue::~DirHistoryQueue() {} void DirHistoryQueue::clear() { _urlQueue.clear(); _currentItems.clear(); _currentPos = 0; } QUrl DirHistoryQueue::currentUrl() { if(_urlQueue.count()) return _urlQueue[_currentPos]; else return QUrl(); } void DirHistoryQueue::setCurrentUrl(const QUrl &url) { if(_urlQueue.count()) _urlQueue[_currentPos] = url; } QString DirHistoryQueue::currentItem() { if(count()) return _currentItems[_currentPos]; else return QString(); } void DirHistoryQueue::saveCurrentItem() { // if the filesystem-url hasn't been refreshed yet, // avoid saving current item for the wrong url if(count() && _panel->virtualPath().matches(_urlQueue[_currentPos], QUrl::StripTrailingSlash)) _currentItems[_currentPos] = _panel->view->getCurrentItem(); } void DirHistoryQueue::add(QUrl url, QString currentItem) { url.setPath(QDir::cleanPath(url.path())); if(_urlQueue.isEmpty()) { _urlQueue.push_front(url); _currentItems.push_front(currentItem); return; } if(_urlQueue[_currentPos].matches(url, QUrl::StripTrailingSlash)) { _currentItems[_currentPos] = currentItem; return; } for (int i = 0; i < _currentPos; i++) { _urlQueue.pop_front(); _currentItems.pop_front(); } _currentPos = 0; // do we have room for another ? if (_urlQueue.count() > 12) { // FIXME: use user-defined size // no room - remove the oldest entry _urlQueue.pop_back(); _currentItems.pop_back(); } saveCurrentItem(); _urlQueue.push_front(url); _currentItems.push_front(currentItem); } bool DirHistoryQueue::gotoPos(int pos) { if(pos >= 0 && pos < _urlQueue.count()) { saveCurrentItem(); _currentPos = pos; return true; } return false; } bool DirHistoryQueue::goBack() { return gotoPos(_currentPos + 1); } bool DirHistoryQueue::goForward() { return gotoPos(_currentPos - 1); } void DirHistoryQueue::save(KConfigGroup cfg) { saveCurrentItem(); QList urls; foreach(const QUrl &url, _urlQueue) { // make sure no passwords are permanently stored QUrl safeUrl(url); safeUrl.setPassword(QString()); urls << safeUrl; } cfg.writeEntry("Entrys", KrServices::toStringList(urls)); cfg.writeEntry("CurrentItems", _currentItems); cfg.writeEntry("CurrentIndex", _currentPos); } bool DirHistoryQueue::restore(KConfigGroup cfg) { clear(); _urlQueue = KrServices::toUrlList(cfg.readEntry("Entrys", QStringList())); _currentItems = cfg.readEntry("CurrentItems", QStringList()); if(!_urlQueue.count() || _urlQueue.count() != _currentItems.count()) { clear(); return false; } _currentPos = cfg.readEntry("CurrentIndex", 0); if(_currentPos >= _urlQueue.count() || _currentPos < 0) _currentPos = 0; return true; } diff --git a/krusader/Panel/krpopupmenu.cpp b/krusader/Panel/krpopupmenu.cpp index 87f004e9..9d10b221 100644 --- a/krusader/Panel/krpopupmenu.cpp +++ b/krusader/Panel/krpopupmenu.cpp @@ -1,444 +1,444 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krpopupmenu.h" // QtGui #include #include #include #include #include #include #include #include #include #include #include #include -#include "krview.h" -#include "krviewitem.h" #include "listpanel.h" #include "listpanelactions.h" #include "panelfunc.h" +#include "PanelView/krview.h" +#include "PanelView/krviewitem.h" #include "../defaults.h" #include "../krservices.h" #include "../krslots.h" #include "../krusader.h" #include "../krusaderview.h" #include "../panelmanager.h" #include "../Archive/krarchandler.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/filesystem.h" #include "../FileSystem/krtrashhandler.h" #include "../MountMan/kmountman.h" #include "../UserAction/useractionpopupmenu.h" void KrPopupMenu::run(const QPoint &pos, KrPanel *panel) { KrPopupMenu menu(panel); QAction * res = menu.exec(pos); int result = -1; if (res && res->data().canConvert()) result = res->data().toInt(); menu.performAction(result); } /** * Copied from dolphin/src/dolphincontextmenu.cpp and modified to add only compress and extract submenus. */ void KrPopupMenu::addCompressAndExtractPluginActions() { KFileItemListProperties props(_items); QVector jsonPlugins = KPluginLoader::findPlugins("kf5/kfileitemaction", [=](const KPluginMetaData& metaData) { return metaData.pluginId() == "compressfileitemaction" || metaData.pluginId() == "extractfileitemaction"; }); foreach (const KPluginMetaData &jsonMetadata, jsonPlugins) { KAbstractFileItemActionPlugin* abstractPlugin = KPluginLoader(jsonMetadata.fileName()) .factory()->create(); if (abstractPlugin) { abstractPlugin->setParent(this); addActions(abstractPlugin->actions(props, this)); } } } KrPopupMenu::KrPopupMenu(KrPanel *thePanel, QWidget *parent) : QMenu(parent), panel(thePanel), empty(false), multipleSelections(false) { // selected file names const QStringList fileNames = panel->gui->getSelectedNames(); // file items QList files; for (const QString fileName : fileNames) { files.append(panel->func->files()->getFileItem(fileName)); } // KFileItems for (FileItem *file : files) { _items.append(KFileItem(file->getUrl(), file->getMime(), file->getMode())); } if (files.empty()) { addCreateNewMenu(); addSeparator(); addEmptyMenuEntries(); return; } else if (files.size() > 1) { multipleSelections = true; } QSet protocols; for (FileItem *file : files) { protocols.insert(file->getUrl().scheme()); } const bool inTrash = protocols.contains("trash"); const bool trashOnly = inTrash && protocols.count() == 1; FileItem *file = files.first(); // ------------ the OPEN/BROWSE option - open preferred service QAction * openAct = addAction(i18n("Open/Run")); openAct->setData(QVariant(OPEN_ID)); if (!multipleSelections) { // meaningful only if one file is selected KrViewItemList viewItems; panel->view->getSelectedKrViewItems(&viewItems); openAct->setIcon(viewItems.first()->icon()); openAct->setText(file->isExecutable() && !file->isDir() ? i18n("Run") : i18n("Open")); // open in a new tab (if folder) if (file->isDir()) { QAction * openTab = addAction(i18n("Open in New Tab")); openTab->setData(QVariant(OPEN_TAB_ID)); openTab->setIcon(krLoader->loadIcon("tab-new", KIconLoader::Panel)); openTab->setText(i18n("Open in New Tab")); } // if the file can be browsed as archive... if (!panel->func->browsableArchivePath(file->getName()).isEmpty() // ...but user disabled archive browsing... && (!KConfigGroup(krConfig, "Archives") .readEntry("ArchivesAsDirectories", _ArchivesAsDirectories) // ...or the file is not a standard archive (e.g. odt, docx, etc.)... || !KRarcHandler::arcSupported(file->getMime()))) { // ...it will not be browsed as a directory by default, but add an option for it QAction *browseAct = addAction(i18n("Browse")); browseAct->setData(QVariant(BROWSE_ID)); browseAct->setIcon(krLoader->loadIcon("", KIconLoader::Panel)); browseAct->setText(i18n("Browse Archive")); } addSeparator(); } // ------------- Preview - local filesystem only ? if (panel->func->files()->isLocal()) { // create the preview popup preview.setUrls(panel->func->files()->getUrls(fileNames)); QAction *previewAction = addMenu(&preview); previewAction->setData(QVariant(PREVIEW_ID)); previewAction->setText(i18n("Preview")); previewAction->setIcon(krLoader->loadIcon("document-print-preview", KIconLoader::Small)); } // -------------- Open with: try to find-out which apps can open the file QSet uniqueMimeTypes; for (FileItem *file : files) uniqueMimeTypes.insert(file->getMime()); const QStringList mimeTypes = uniqueMimeTypes.toList(); offers = mimeTypes.count() == 1 ? KMimeTypeTrader::self()->query(mimeTypes.first()) : KFileItemActions::associatedApplications(mimeTypes, QString()); if (!offers.isEmpty()) { for (int i = 0; i < offers.count(); ++i) { QExplicitlySharedDataPointer service = offers[i]; if (service->isValid() && service->isApplication()) { openWith.addAction(krLoader->loadIcon(service->icon(), KIconLoader::Small), service->name())->setData(QVariant(SERVICE_LIST_ID + i)); } } openWith.addSeparator(); if (!multipleSelections && file->isDir()) openWith.addAction(krLoader->loadIcon("utilities-terminal", KIconLoader::Small), i18n("Terminal"))->setData(QVariant(OPEN_TERM_ID)); openWith.addAction(i18n("Other..."))->setData(QVariant(CHOOSE_ID)); QAction *openWithAction = addMenu(&openWith); openWithAction->setData(QVariant(OPEN_WITH_ID)); openWithAction->setText(i18n("Open With")); openWithAction->setIcon(krLoader->loadIcon("document-open", KIconLoader::Small)); addSeparator(); } // --------------- user actions QAction *userAction = new UserActionPopupMenu(file->getUrl()); userAction->setText(i18n("User Actions")); addAction(userAction); // workaround for Bug 372999: application freezes very long time if many files are selected if (_items.length() < 1000) // add compress and extract plugins (if available) addCompressAndExtractPluginActions(); // NOTE: design and usability problem here. Services disabled in kservicemenurc settings won't // be added to the menu. But Krusader does not provide a way do change these settings (only // Dolphin does). fileItemActions.setItemListProperties(KFileItemListProperties(_items)); fileItemActions.addServiceActionsTo(this); addSeparator(); // ------------- 'create new' submenu addCreateNewMenu(); addSeparator(); // ---------- COPY addAction(i18n("Copy..."))->setData(QVariant(COPY_ID)); // ------- MOVE addAction(i18n("Move..."))->setData(QVariant(MOVE_ID)); // ------- RENAME - only one file if (!multipleSelections && !inTrash) { addAction(krLoader->loadIcon("edit-rename", KIconLoader::Small), i18n("Rename"))->setData(QVariant(RENAME_ID)); } // -------- MOVE TO TRASH if (KConfigGroup(krConfig, "General").readEntry("Move To Trash", _MoveToTrash) && panel->func->files()->canMoveToTrash(fileNames)) { addAction(krLoader->loadIcon("user-trash", KIconLoader::Small), i18n("Move to Trash"))->setData(QVariant(TRASH_ID)); } // -------- DELETE addAction(krLoader->loadIcon("edit-delete", KIconLoader::Small), i18n("Delete"))->setData(QVariant(DELETE_ID)); // -------- SHRED - only one file /* if ( panel->func->files() ->getType() == filesystem:fileSystemM_NORMAL && !fileitem->isDir() && !multipleSelections ) addAction( i18n( "Shred" ) )->setData( QVariant( SHRED_ID ) );*/ // ---------- link handling // create new shortcut or redirect links - only on local directories: if (panel->func->files()->isLocal()) { addSeparator(); linkPopup.addAction(i18n("New Symlink..."))->setData(QVariant(NEW_SYMLINK_ID)); linkPopup.addAction(i18n("New Hardlink..."))->setData(QVariant(NEW_LINK_ID)); if (file->isSymLink()) linkPopup.addAction(i18n("Redirect Link..."))->setData(QVariant(REDIRECT_LINK_ID)); QAction *linkAction = addMenu(&linkPopup); linkAction->setData(QVariant(LINK_HANDLING_ID)); linkAction->setText(i18n("Link Handling")); linkAction->setIcon(krLoader->loadIcon("insert-link", KIconLoader::Small)); } addSeparator(); // ---------- calculate space if (panel->func->files()->isLocal() && (file->isDir() || multipleSelections)) addAction(panel->gui->actions()->actCalculate); // ---------- mount/umount/eject if (panel->func->files()->isLocal() && file->isDir() && !multipleSelections) { const QString selectedDirectoryPath = file->getUrl().path(); if (krMtMan.getStatus(selectedDirectoryPath) == KMountMan::MOUNTED) addAction(i18n("Unmount"))->setData(QVariant(UNMOUNT_ID)); else if (krMtMan.getStatus(selectedDirectoryPath) == KMountMan::NOT_MOUNTED) addAction(i18n("Mount"))->setData(QVariant(MOUNT_ID)); if (krMtMan.ejectable(selectedDirectoryPath)) addAction(i18n("Eject"))->setData(QVariant(EJECT_ID)); } // --------- send by mail if (KrServices::supportedTools().contains("MAIL") && !file->isDir()) { addAction(krLoader->loadIcon("mail-send", KIconLoader::Small), i18n("Send by Email"))->setData(QVariant(SEND_BY_EMAIL_ID)); } // --------- empty trash if (trashOnly) { addAction(i18n("Restore"))->setData(QVariant(RESTORE_TRASHED_FILE_ID)); addAction(i18n("Empty Trash"))->setData(QVariant(EMPTY_TRASH_ID)); } #ifdef SYNCHRONIZER_ENABLED // --------- synchronize if (panel->view->numSelected()) { addAction(i18n("Synchronize Selected Files..."))->setData(QVariant(SYNC_SELECTED_ID)); } #endif // --------- copy/paste addSeparator(); addAction(krLoader->loadIcon("edit-copy", KIconLoader::Small), i18n("Copy to Clipboard"))->setData(QVariant(COPY_CLIP_ID)); addAction(krLoader->loadIcon("edit-cut", KIconLoader::Small), i18n("Cut to Clipboard"))->setData(QVariant(MOVE_CLIP_ID)); addAction(krLoader->loadIcon("edit-paste", KIconLoader::Small), i18n("Paste from Clipboard"))->setData(QVariant(PASTE_CLIP_ID)); addSeparator(); // --------- properties addAction(panel->gui->actions()->actProperties); } void KrPopupMenu::addEmptyMenuEntries() { addAction(i18n("Paste from Clipboard"))->setData(QVariant(PASTE_CLIP_ID)); } void KrPopupMenu::addCreateNewMenu() { createNewPopup.addAction(krLoader->loadIcon("folder", KIconLoader::Small), i18n("Folder..."))->setData(QVariant(MKDIR_ID)); createNewPopup.addAction(krLoader->loadIcon("text-plain", KIconLoader::Small), i18n("Text File..."))->setData(QVariant(NEW_TEXT_FILE_ID)); QAction *newAction = addMenu(&createNewPopup); newAction->setData(QVariant(CREATE_NEW_ID)); newAction->setText(i18n("Create New")); newAction->setIcon(krLoader->loadIcon("document-new", KIconLoader::Small)); } void KrPopupMenu::performAction(int id) { if (_items.isEmpty()) return; // sanity check, empty file list KFileItem *item = &_items.first(); switch (id) { case - 1 : // the user clicked outside of the menu return ; case OPEN_TAB_ID : // assuming only 1 file is selected (otherwise we won't get here) panel->manager()->newTab(item->url(), panel); break; case OPEN_ID : foreach(const KFileItem &fi, _items) panel->func->execute(fi.name()); break; case BROWSE_ID : panel->func->goInside(item->url().fileName()); break; case COPY_ID : panel->func->copyFiles(); break; case MOVE_ID : panel->func->moveFiles(); break; case RENAME_ID : panel->func->rename(); break; case TRASH_ID : panel->func->deleteFiles(true); break; case DELETE_ID : panel->func->deleteFiles(false); break; case EJECT_ID : krMtMan.eject(item->url().adjusted(QUrl::StripTrailingSlash).path()); break; /* case SHRED_ID : if ( KMessageBox::warningContinueCancel( krApp, i18n("Do you really want to shred %1? Once shred, the file is gone forever.", item->name()), QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "Shred" ) == KMessageBox::Continue ) KShred::shred( panel->func->files() ->getFile( item->name() ).adjusted(QUrl::RemoveTrailingSlash).path() ); break;*/ case OPEN_KONQ_ID : KToolInvocation::startServiceByDesktopName("konqueror", item->url().toDisplayString(QUrl::PreferLocalFile)); break; case CHOOSE_ID : // open-with dialog panel->func->displayOpenWithDialog(_items.urlList()); break; case MOUNT_ID : krMtMan.mount(item->url().adjusted(QUrl::StripTrailingSlash).path()); break; case NEW_LINK_ID : panel->func->krlink(false); break; case NEW_SYMLINK_ID : panel->func->krlink(true); break; case REDIRECT_LINK_ID : panel->func->redirectLink(); break; case EMPTY_TRASH_ID : KrTrashHandler::emptyTrash(); break; case RESTORE_TRASHED_FILE_ID : KrTrashHandler::restoreTrashedFiles(_items.urlList()); break; case UNMOUNT_ID : krMtMan.unmount(item->url().adjusted(QUrl::StripTrailingSlash).path()); break; case COPY_CLIP_ID : panel->func->copyToClipboard(); break; case MOVE_CLIP_ID : panel->func->copyToClipboard(true); break; case PASTE_CLIP_ID : panel->func->pasteFromClipboard(); break; case SEND_BY_EMAIL_ID : { SLOTS->sendFileByEmail(_items.urlList()); break; } case MKDIR_ID : panel->func->mkdir(); break; case NEW_TEXT_FILE_ID: panel->func->editNew(); break; #ifdef SYNCHRONIZER_ENABLED case SYNC_SELECTED_ID : { QStringList selectedNames; foreach(const KFileItem &item, _items) selectedNames << item.name(); if (panel->otherPanel()->view->numSelected()) { KrViewItemList otherItems; panel->otherPanel()->view->getSelectedKrViewItems(&otherItems); for (KrViewItemList::Iterator it2 = otherItems.begin(); it2 != otherItems.end(); ++it2) { QString name = (*it2) ->name(); if (!selectedNames.contains(name)) selectedNames.append(name); } } SLOTS->slotSynchronizeDirs(selectedNames); } break; #endif case OPEN_TERM_ID : SLOTS->runTerminal(item->url().path()); break; } // check if something from the open-with-offered-services was selected if (id >= SERVICE_LIST_ID) { const QStringList names = panel->gui->getSelectedNames(); panel->func->runService(*(offers[ id - SERVICE_LIST_ID ]), panel->func->files()->getUrls(names)); } } diff --git a/krusader/Panel/krpreviewjob.cpp b/krusader/Panel/krpreviewjob.cpp index bf8089fa..fe10c2ac 100644 --- a/krusader/Panel/krpreviewjob.cpp +++ b/krusader/Panel/krpreviewjob.cpp @@ -1,172 +1,172 @@ /*************************************************************************** krpreviewjob.cpp ------------------- copyright : (C) 2009 by Jan Lepper e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krpreviewjob.h" #include "krpreviews.h" -#include "krview.h" -#include "krviewitem.h" +#include "PanelView/krview.h" +#include "PanelView/krviewitem.h" #include "../FileSystem/fileitem.h" #include "../defaults.h" #include // QtWidgets #include #define ASSERT(what) if(!what) abort(); // how much items to process by a single job // view becomes unresponsive during load if set too high #define MAX_CHUNK_SIZE 50 KrPreviewJob::KrPreviewJob(KrPreviews *parent) : _job(0), _parent(parent) { _timer.setSingleShot(true); _timer.setInterval(0); connect(&_timer, SIGNAL(timeout()), SLOT(slotStartJob())); } KrPreviewJob::~KrPreviewJob() { doKill(); } void KrPreviewJob::scheduleItem(KrViewItem *item) { if(!_scheduled.contains(item)) { _scheduled.append(item); setTotalAmount(KJob::Files, totalAmount(KJob::Files) + 1); } if(!_job) _timer.start(); } void KrPreviewJob::removeItem(KrViewItem *item) { setTotalAmount(KJob::Files, totalAmount(KJob::Files) - _scheduled.removeAll(item)); if(_job) { doKill(); if(!_scheduled.isEmpty()) _timer.start(); } if(_scheduled.isEmpty()) emitResult(); } void KrPreviewJob::slotFailed(const KFileItem & item) { slotGotPreview(item, QPixmap()); } void KrPreviewJob::slotGotPreview(const KFileItem & item, const QPixmap & preview) { KrViewItem *vi = _hash[item]; ASSERT(vi); _scheduled.removeOne(vi); const FileItem *file = vi->getFileItem(); _parent->addPreview(file, preview); vi->redraw(); setProcessedAmount(KJob::Files, processedAmount(KJob::Files) + 1); emitPercent(processedAmount(KJob::Files), totalAmount(KJob::Files)); } void KrPreviewJob::slotStartJob() { ASSERT(_job == 0); ASSERT(!_scheduled.isEmpty()); _hash.clear(); sort(); int size = _parent->_view->fileIconSize(); KFileItemList list; for(int i = 0; i < _scheduled.count() && i < MAX_CHUNK_SIZE; i++) { KFileItem fi(_scheduled[i]->getFileItem()->getUrl(), 0, 0); list.append(fi); _hash.insert(fi, _scheduled[i]); } QStringList allPlugins = KIO::PreviewJob::availablePlugins(); _job = new KIO::PreviewJob(list, QSize(size, size), &allPlugins); _job->setOverlayIconAlpha(0); _job->setOverlayIconSize(0); _job->setScaleType(KIO::PreviewJob::ScaledAndCached); connect(_job, SIGNAL(gotPreview(KFileItem,QPixmap)), SLOT(slotGotPreview(KFileItem,QPixmap))); connect(_job, SIGNAL(failed(KFileItem)), SLOT(slotFailed(KFileItem))); connect(_job, SIGNAL(result(KJob*)), SLOT(slotJobResult(KJob*))); } void KrPreviewJob::slotJobResult(KJob *job) { (void) job; if(!disconnect(_job, 0, this, 0)) abort(); _job = 0; _hash.clear(); if(_scheduled.isEmpty()) emitResult(); else _timer.start(); } // move currently visible items to beginning of the list void KrPreviewJob::sort() { for(int i = 0, visible_end = 0; i < _scheduled.count(); i++) { KrViewItem *item = _scheduled[i]; if(_parent->_view->widget()->rect().intersects(item->itemRect())) { if(i != visible_end) _scheduled.move(i, visible_end); visible_end++; } } } bool KrPreviewJob::doKill() { _timer.stop(); if(_job) { if(!disconnect(_job, 0, this, 0)) abort(); if(!_job->kill()) abort(); _job = 0; } _hash.clear(); return true; } diff --git a/krusader/Panel/krpreviews.cpp b/krusader/Panel/krpreviews.cpp index 391a2384..3894a2dd 100644 --- a/krusader/Panel/krpreviews.cpp +++ b/krusader/Panel/krpreviews.cpp @@ -1,140 +1,140 @@ /*************************************************************************** krpreviews.cpp ------------------- copyright : (C) 2009 by Jan Lepper e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krpreviews.h" #include "krpreviewjob.h" #include "krcolorcache.h" -#include "krview.h" -#include "krviewitem.h" +#include "PanelView/krview.h" +#include "PanelView/krviewitem.h" #include "../FileSystem/fileitem.h" #include "../defaults.h" #include #define ASSERT(what) if(!what) abort(); KrPreviews::KrPreviews(KrView *view) : _job(0), _view(view) { _dim = KrColorCache::getColorCache().getDimSettings(_dimColor, _dimFactor); connect(&KrColorCache::getColorCache(), SIGNAL(colorsRefreshed()), SLOT(slotRefreshColors())); } KrPreviews::~KrPreviews() { clear(); } void KrPreviews::clear() { if(_job) { _job->kill(KJob::EmitResult); _job = 0; } _previews.clear(); _previewsInactive.clear(); } void KrPreviews::update() { if(_job) return; for (KrViewItem *it = _view->getFirst(); it != 0; it = _view->getNext(it)) { if(!_previews.contains(it->getFileItem())) updatePreview(it); } } void KrPreviews::deletePreview(KrViewItem *item) { if(_job) { _job->removeItem(item); } removePreview(item->getFileItem()); } void KrPreviews::updatePreview(KrViewItem *item) { if(!_job) { _job = new KrPreviewJob(this); connect(_job, SIGNAL(result(KJob*)), SLOT(slotJobResult(KJob*))); _view->op()->emitPreviewJobStarted(_job); } _job->scheduleItem(item); } bool KrPreviews::getPreview(const FileItem *file, QPixmap &pixmap, bool active) { if(active || !_dim) pixmap = _previews.value(file); else pixmap = _previewsInactive.value(file); return !pixmap.isNull(); } void KrPreviews::slotJobResult(KJob *job) { (void) job; _job = 0; } void KrPreviews::slotRefreshColors() { clear(); _dim = KrColorCache::getColorCache().getDimSettings(_dimColor, _dimFactor); update(); } void KrPreviews::addPreview(const FileItem *file, const QPixmap &preview) { QPixmap active, inactive; if(preview.isNull()) { active = KrView::getIcon((FileItem *)file, true, _view->fileIconSize()); if(_dim) inactive = KrView::getIcon((FileItem *)file, false, _view->fileIconSize()); } else { active = KrView::processIcon(preview, false, _dimColor, _dimFactor, file->isSymLink()); if(_dim) inactive = KrView::processIcon(preview, true, _dimColor, _dimFactor, file->isSymLink()); } _previews.insert(file, active); if(_dim) _previewsInactive.insert(file, inactive); } void KrPreviews::removePreview(const FileItem *file) { _previews.remove(file); _previewsInactive.remove(file); } diff --git a/krusader/Panel/krsearchbar.cpp b/krusader/Panel/krsearchbar.cpp index 977f1a5d..044f144f 100644 --- a/krusader/Panel/krsearchbar.cpp +++ b/krusader/Panel/krsearchbar.cpp @@ -1,394 +1,394 @@ /***************************************************************************** * Copyright (C) 2010 Jan Lepper * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krsearchbar.h" +#include "PanelView/krview.h" +#include "PanelView/krviewitem.h" +#include "../FileSystem/dirlisterinterface.h" #include "../defaults.h" #include "../krglobal.h" -#include "../FileSystem/dirlisterinterface.h" -#include "krview.h" -#include "krviewitem.h" #include #include #include #include #include #include #include #include #include KrSearchBar::KrSearchBar(KrView *view, QWidget *parent) : QWidget(parent), _view(0) { // close button QToolButton *closeButton = new QToolButton(this); closeButton->setAutoRaise(true); closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); closeButton->setToolTip(i18n("Close the search bar")); connect(closeButton, SIGNAL(clicked()), SLOT(hideBar())); // combo box for changing search mode _modeBox = new QComboBox(this); _modeBox->addItems(QStringList() << i18n("Search") << i18n("Select") << i18n("Filter")); int defaultIndex = KConfigGroup (krConfig, "Look&Feel") .readEntry("Default Search Mode", QString::number(KrSearchBar::MODE_SEARCH)).toInt(); _modeBox->setCurrentIndex(defaultIndex); _modeBox->setToolTip(i18n("Change the search mode")); connect(_modeBox, SIGNAL(currentIndexChanged(int)), SLOT(onModeChange())); _currentMode = static_cast(_modeBox->currentIndex()); // combo box for entering search string _textBox = new KComboBox(this); _textBox->setEditable(true); _modeBox->setToolTip(i18n("Enter or select search string")); QStringList savedSearches = KConfigGroup(krConfig, "Private") .readEntry("Predefined Selections", QStringList()); if (savedSearches.count() > 0) _textBox->addItems(savedSearches); _textBox->setCurrentText(""); _textBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred)); connect(_textBox, SIGNAL(currentTextChanged(QString)), SLOT(onSearchChange())); QToolButton *saveSearchBtn = new QToolButton(this); saveSearchBtn->setIcon(krLoader->loadIcon("document-save", KIconLoader::Toolbar, 16)); saveSearchBtn->setFixedSize(20, 20); saveSearchBtn->setToolTip(i18n("Save the current search string")); connect(saveSearchBtn, SIGNAL(clicked()), this, SLOT(saveSearchString())); _openSelectDialogBtn = new QToolButton(this); _openSelectDialogBtn->setIcon(krLoader->loadIcon("configure", KIconLoader::Toolbar, 16)); _openSelectDialogBtn->setFixedSize(20, 20); _openSelectDialogBtn->setToolTip(i18n("Open selection dialog")); QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); layout->addWidget(closeButton); layout->addWidget(_modeBox); layout->addWidget(_textBox); layout->addWidget(saveSearchBtn); layout->addWidget(_openSelectDialogBtn); _textBox->installEventFilter(this); setView(view); } void KrSearchBar::setView(KrView *view) { if (_view) { _view->widget()->removeEventFilter(this); disconnect(_openSelectDialogBtn, 0, 0, 0); } _view = view; connect(_openSelectDialogBtn, &QToolButton::clicked, [this](){ _view->customSelection(true); }); _view->widget()->installEventFilter(this); } // #### public slots void KrSearchBar::showBar(SearchMode mode) { if (mode != MODE_LAST) { _modeBox->setCurrentIndex(mode); } show(); _textBox->setFocus(); } void KrSearchBar::hideBar() { resetSearch(); if (_textBox->hasFocus()) _view->widget()->setFocus(); hide(); } void KrSearchBar::resetSearch() { _textBox->clearEditText(); indicateMatch(true); } // #### protected slots void KrSearchBar::onModeChange() { if (_currentMode == MODE_FILTER) { _view->op()->filterSearch(QString(), true); // reset filter } _currentMode = static_cast(_modeBox->currentIndex()); onSearchChange(); } void KrSearchBar::onSearchChange() { const QString text = _textBox->currentText(); switch(_currentMode) { case MODE_SEARCH: { const bool anyMatch = _view->op()->searchItem(text, caseSensitive()); indicateMatch(anyMatch); break; } case MODE_SELECT: { _view->unselectAll(); if (!text.isEmpty()) { const bool anyMatch = _view->changeSelection(KRQuery(text, caseSensitive()), true); indicateMatch(anyMatch); } break; } case MODE_FILTER: { const bool anyMatch =_view->op()->filterSearch(text, caseSensitive()); indicateMatch(anyMatch); break; } default: krOut << "unexpected search mode: " << _currentMode; } _textBox->setFocus(); } void KrSearchBar::saveSearchString() { KConfigGroup group(krConfig, "Private"); QStringList lst = group.readEntry("Predefined Selections", QStringList()); QString searchString = _textBox->currentText(); if (lst.indexOf(searchString) != -1) { // already saved return; } lst.append(searchString); group.writeEntry("Predefined Selections", lst); _textBox->addItem(searchString); QToolTip::showText(QCursor::pos(), i18n("Saved search text to history")); } // #### protected void KrSearchBar::keyPressEvent(QKeyEvent *event) { const bool handled = handleKeyPressEvent(static_cast(event)); if (handled) { return; } QWidget::keyPressEvent(event); } bool KrSearchBar::eventFilter(QObject *watched, QEvent *event) { if (event->type() != QEvent::ShortcutOverride && watched == _view->widget()) { QKeyEvent *ke = static_cast(event); // overwrite "escape" shortcut if bar is shown if ((ke->key() == Qt::Key_Escape) && (ke->modifiers() == Qt::NoModifier) && !isHidden()) { ke->accept(); handleKeyPressEvent(ke); return true; } } if (event->type() != QEvent::KeyPress) { return false; } QKeyEvent *ke = static_cast(event); if (watched == _view->widget()) { KConfigGroup grpSv(krConfig, "Look&Feel"); const bool autoShow = grpSv.readEntry("New Style Quicksearch", _NewStyleQuicksearch); if (isHidden() && !autoShow) { return false; } if (!isHidden()) { const bool handled = handleKeyPressEvent(ke); if (handled) { return true; } } if (isHidden() || // view can handle its own event if user does not want to remove text or... !((ke->key() == Qt::Key_Backspace && !_textBox->currentText().isEmpty()) || // ...insert space in search bar (even if not focused) (ke->key() == Qt::Key_Space && _currentMode == KrSearchBar::MODE_SEARCH))) { const bool handled = _view->handleKeyEvent(ke); if (handled) { return true; } } if (ke->text().isEmpty() || (ke->modifiers() != Qt::NoModifier && ke->modifiers() != Qt::ShiftModifier && ke->modifiers() != Qt::KeypadModifier)) { return false; } // start searching if bar is hidden? if (isHidden()) { if (autoShow) { showBar(); } else { return false; } } // bar is visible and gets the key input _textBox->setFocus(); if (ke->key() == Qt::Key_Backspace) { _textBox->lineEdit()->backspace(); } else { _textBox->setEditText(_textBox->currentText().append(ke->text())); } return true; } else if (watched == _textBox) { // allow the view to handle (most) key events from the text box if (ke->modifiers() == Qt::NoModifier && ke->key() != Qt::Key_Space && ke->key() != Qt::Key_Backspace && ke->key() != Qt::Key_Left && ke->key() != Qt::Key_Right) { bool handled = _view->handleKeyEvent(ke); if (handled) { _view->widget()->setFocus(); return true; } } } return false; } // #### private bool KrSearchBar::handleKeyPressEvent(QKeyEvent *ke) { if (ke->modifiers() != Qt::NoModifier) { return false; } switch (ke->key()) { case Qt::Key_Escape: { hideBar(); return true; } case Qt::Key_Up: return handleUpDownKeyPress(true); case Qt::Key_Down: return handleUpDownKeyPress(false); case Qt::Key_Insert: { // select current item and jump to next search result KrViewItem * item = _view->getCurrentKrViewItem(); if (item) { item->setSelected(!item->isSelected()); _view->op()->searchItem(_textBox->currentText(), caseSensitive(), 1); } return true; } case Qt::Key_Home: { // jump to first search result KrViewItem * item = _view->getLast(); if (item) { _view->setCurrentKrViewItem(_view->getLast()); _view->op()->searchItem(_textBox->currentText(), caseSensitive(), 1); } return true; } case Qt::Key_End: { // jump to last search result KrViewItem * item = _view->getFirst(); if (item) { _view->setCurrentKrViewItem(_view->getFirst()); _view->op()->searchItem(_textBox->currentText(), caseSensitive(), -1); } return true; } } return false; } bool KrSearchBar::handleUpDownKeyPress(bool up) { if (_currentMode != MODE_SEARCH) { return false; } const bool updownCancel = KConfigGroup(krConfig, "Look&Feel") .readEntry("Up/Down Cancels Quicksearch", false); if (updownCancel) { hideBar(); return false; } const bool anyMatch = _view->op()->searchItem(_textBox->currentText(), caseSensitive(), up ? -1 : 1); indicateMatch(anyMatch); return true; } void KrSearchBar::indicateMatch(bool anyMatch) { KConfigGroup gc(krConfig, "Colors"); QPalette p = QGuiApplication::palette(); QString foreground, background; if (anyMatch) { foreground = "Quicksearch Match Foreground"; background = "Quicksearch Match Background"; } else { foreground = "Quicksearch Non-match Foreground"; background = "Quicksearch Non-match Background"; } QColor fore = Qt::black; QString foreSetting = gc.readEntry(foreground, QString()); if (foreSetting == "KDE default") { fore = p.color(QPalette::Active, QPalette::Text); } else if (!foreSetting.isEmpty()) { fore = gc.readEntry(foreground, fore); } QColor back = anyMatch ? QColor(192, 255, 192) : QColor(255, 192, 192); QString backSetting = gc.readEntry(background, QString()); if (backSetting == "KDE default") { back = p.color(QPalette::Active, QPalette::Base); } else if (!backSetting.isEmpty()) { back = gc.readEntry(background, back); } QPalette pal = palette(); pal.setColor(QPalette::Base, back); pal.setColor(QPalette::Text, fore); _textBox->lineEdit()->setPalette(pal); } bool KrSearchBar::caseSensitive() { KConfigGroup grpSvr(krConfig, "Look&Feel"); return grpSvr.readEntry("Case Sensitive Quicksearch", _CaseSensitiveQuicksearch); } diff --git a/krusader/Panel/listpanel.cpp b/krusader/Panel/listpanel.cpp index 52893fb4..a7d7399c 100644 --- a/krusader/Panel/listpanel.cpp +++ b/krusader/Panel/listpanel.cpp @@ -1,1366 +1,1366 @@ /*************************************************************************** listpanel.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "listpanel.h" // QtCore #include #include #include #include #include #include #include // QtGui #include #include #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dirhistoryqueue.h" #include "krcolorcache.h" #include "krerrordisplay.h" #include "krlayoutfactory.h" #include "krpopupmenu.h" #include "krpreviewpopup.h" #include "krsearchbar.h" -#include "krview.h" -#include "krviewfactory.h" -#include "krviewitem.h" #include "listpanelactions.h" #include "panelfunc.h" #include "panelpopup.h" #include "viewactions.h" +#include "PanelView/krview.h" +#include "PanelView/krviewfactory.h" +#include "PanelView/krviewitem.h" #include "../defaults.h" #include "../kicons.h" #include "../krservices.h" #include "../krslots.h" #include "../krusader.h" #include "../krusaderview.h" #include "../Archive/krarchandler.h" #include "../BookMan/krbookmarkbutton.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/filesystem.h" #include "../FileSystem/krpermhandler.h" #include "../FileSystem/sizecalculator.h" #include "../Dialogs/krdialogs.h" #include "../Dialogs/krspwidgets.h" #include "../Dialogs/krsqueezedtextlabel.h" #include "../Dialogs/percentalsplitter.h" #include "../Dialogs/popularurls.h" #include "../GUI/dirhistorybutton.h" #include "../GUI/kcmdline.h" #include "../GUI/mediabutton.h" #include "../MountMan/kmountman.h" #include "../UserAction/useractionpopupmenu.h" class ActionButton : public QToolButton { public: ActionButton(QWidget *parent, ListPanel *panel, QAction *action, QString text = QString()) : QToolButton(parent), panel(panel), action(action) { setText(text); setAutoRaise(true); if(KConfigGroup(krConfig, "ListPanelButtons").readEntry("Icons", false) || text.isEmpty()) setIcon(action->icon()); setToolTip(action->toolTip()); } protected: virtual void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE { panel->slotFocusOnMe(); action->trigger(); } ListPanel *panel; QAction *action; }; ///////////////////////////////////////////////////// // The list panel constructor // ///////////////////////////////////////////////////// ListPanel::ListPanel(QWidget *parent, AbstractPanelManager *manager, KConfigGroup cfg) : QWidget(parent), KrPanel(manager, this, new ListPanelFunc(this)), panelType(-1), colorMask(255), compareMode(false), previewJob(0), inlineRefreshJob(0), searchBar(0), cdRootButton(0), cdUpButton(0), popupBtn(0), popup(0), fileSystemError(0), _navigatorUrl(), _locked(false) { if(cfg.isValid()) panelType = cfg.readEntry("Type", -1); if (panelType == -1) panelType = defaultPanelType(); _actions = krApp->listPanelActions(); setAcceptDrops(true); QHash widgets; #define ADD_WIDGET(widget) widgets.insert(#widget, widget); // media button mediaButton = new MediaButton(this); connect(mediaButton, SIGNAL(aboutToShow()), this, SLOT(slotFocusOnMe())); connect(mediaButton, SIGNAL(openUrl(QUrl)), func, SLOT(openUrl(QUrl))); connect(mediaButton, SIGNAL(newTab(QUrl)), SLOT(newTab(QUrl))); ADD_WIDGET(mediaButton); // status bar status = new KrSqueezedTextLabel(this); KConfigGroup group(krConfig, "Look&Feel"); status->setFont(group.readEntry("Filelist Font", _FilelistFont)); status->setAutoFillBackground(false); status->setText(""); // needed for initialization code! status->setWhatsThis(i18n("The statusbar displays information about the filesystem " "which holds your current folder: total size, free space, " "type of filesystem, etc.")); ADD_WIDGET(status); // back button backButton = new ActionButton(this, this, _actions->actHistoryBackward); ADD_WIDGET(backButton); // forward button forwardButton = new ActionButton(this, this, _actions->actHistoryForward); ADD_WIDGET(forwardButton); // ... create the history button historyButton = new DirHistoryButton(func->history, this); connect(historyButton, SIGNAL(aboutToShow()), this, SLOT(slotFocusOnMe())); connect(historyButton, SIGNAL(gotoPos(int)), func, SLOT(historyGotoPos(int))); ADD_WIDGET(historyButton); // bookmarks button bookmarksButton = new KrBookmarkButton(this); connect(bookmarksButton, SIGNAL(aboutToShow()), this, SLOT(slotFocusOnMe())); connect(bookmarksButton, SIGNAL(openUrl(QUrl)), func, SLOT(openUrl(QUrl))); bookmarksButton->setWhatsThis(i18n("Open menu with bookmarks. You can also add " "current location to the list, edit bookmarks " "or add subfolder to the list.")); ADD_WIDGET(bookmarksButton); // url input field urlNavigator = new KUrlNavigator(new KFilePlacesModel(this), QUrl(), this); urlNavigator->setWhatsThis(i18n("Name of folder where you are. You can also " "enter name of desired location to move there. " "Use of Net protocols like ftp or fish is possible.")); // handle certain key events here in event filter urlNavigator->editor()->installEventFilter(this); urlNavigator->setUrlEditable(isNavigatorEditModeSet()); urlNavigator->setShowFullPath(group.readEntry("Navigator Full Path", false)); connect(urlNavigator, SIGNAL(returnPressed()), this, SLOT(slotFocusOnMe())); connect(urlNavigator, &KUrlNavigator::urlChanged, this, &ListPanel::slotNavigatorUrlChanged); connect(urlNavigator->editor()->lineEdit(), &QLineEdit::editingFinished, this, &ListPanel::resetNavigatorMode); connect(urlNavigator, SIGNAL(tabRequested(QUrl)), this, SLOT(newTab(QUrl))); connect(urlNavigator, SIGNAL(urlsDropped(QUrl,QDropEvent*)), this, SLOT(handleDrop(QUrl,QDropEvent*))); ADD_WIDGET(urlNavigator); // toolbar QWidget * toolbar = new QWidget(this); QHBoxLayout * toolbarLayout = new QHBoxLayout(toolbar); toolbarLayout->setContentsMargins(0, 0, 0, 0); toolbarLayout->setSpacing(0); ADD_WIDGET(toolbar); fileSystemError = new KrErrorDisplay(this); fileSystemError->setWordWrap(true); fileSystemError->hide(); ADD_WIDGET(fileSystemError); // client area clientArea = new QWidget(this); QVBoxLayout *clientLayout = new QVBoxLayout(clientArea); clientLayout->setSpacing(0); clientLayout->setContentsMargins(0, 0, 0, 0); ADD_WIDGET(clientArea); // totals label totals = new KrSqueezedTextLabel(this); totals->setFont(group.readEntry("Filelist Font", _FilelistFont)); totals->setAutoFillBackground(false); totals->setWhatsThis(i18n("The totals bar shows how many files exist, " "how many selected and the bytes math")); ADD_WIDGET(totals); // free space label freeSpace = new KrSqueezedTextLabel(this); freeSpace->setFont(group.readEntry("Filelist Font", _FilelistFont)); freeSpace->setAutoFillBackground(false); freeSpace->setText(""); freeSpace->setAlignment(Qt::AlignRight | Qt::AlignVCenter); ADD_WIDGET(freeSpace); // progress indicator and cancel button for the quick calc size quickSizeCalcProgress = new QProgressBar(this); quickSizeCalcProgress->hide(); ADD_WIDGET(quickSizeCalcProgress); cancelQuickSizeCalcButton = new QToolButton(this); cancelQuickSizeCalcButton->hide(); cancelQuickSizeCalcButton->setIcon(krLoader->loadIcon("dialog-cancel", KIconLoader::Toolbar, 16)); cancelQuickSizeCalcButton->setToolTip(i18n("Cancel directory space calculation")); ADD_WIDGET(cancelQuickSizeCalcButton); // progress indicator for the preview job previewProgress = new QProgressBar(this); previewProgress->hide(); ADD_WIDGET(previewProgress); // a cancel button for the filesystem refresh and preview job cancelProgressButton = new QToolButton(this); cancelProgressButton->hide(); cancelProgressButton->setIcon(krLoader->loadIcon("dialog-cancel", KIconLoader::Toolbar, 16)); connect(cancelProgressButton, SIGNAL(clicked()), this, SLOT(cancelProgress())); ADD_WIDGET(cancelProgressButton); // button for changing the panel popup position in the panel popupPositionBtn = new QToolButton(this); popupPositionBtn->hide(); popupPositionBtn->setAutoRaise(true); popupPositionBtn->setIcon(krLoader->loadIcon("exchange-positions", KIconLoader::Toolbar, 16)); popupPositionBtn->setToolTip(i18n("Move popup panel clockwise")); connect(popupPositionBtn, &QToolButton::clicked, [this]() { // moving position clockwise setPopupPosition((popupPosition() + 1) % 4); }); ADD_WIDGET(popupPositionBtn); // a quick button to open the popup panel popupBtn = new QToolButton(this); popupBtn->setAutoRaise(true); popupBtn->setIcon(krLoader->loadIcon("arrow-up", KIconLoader::Toolbar, 16)); connect(popupBtn, &QToolButton::clicked, this, &ListPanel::togglePanelPopup); popupBtn->setToolTip(i18n("Open the popup panel")); ADD_WIDGET(popupBtn); #undef ADD_WIDGET // toolbar buttons cdOtherButton = new ActionButton(toolbar, this, _actions->actCdToOther, "="); toolbarLayout->addWidget(cdOtherButton); cdUpButton = new ActionButton(toolbar, this, _actions->actDirUp, ".."); toolbarLayout->addWidget(cdUpButton); cdHomeButton = new ActionButton(toolbar, this, _actions->actHome, "~"); toolbarLayout->addWidget(cdHomeButton); cdRootButton = new ActionButton(toolbar, this, _actions->actRoot, "/"); toolbarLayout->addWidget(cdRootButton); // create the button for sync-browsing syncBrowseButton = new QToolButton(toolbar); syncBrowseButton->setIcon(QIcon::fromTheme("kr_syncbrowse_off")); syncBrowseButton->setCheckable(true); const QString syncBrowseText = i18n("This button toggles the sync-browse mode.\n" "When active, each folder change is performed in the\n" "active and inactive panel - if possible."); syncBrowseButton->setText(syncBrowseText); syncBrowseButton->setToolTip(syncBrowseText); connect(syncBrowseButton, &QToolButton::toggled, [=](bool checked) { syncBrowseButton->setIcon( QIcon::fromTheme(checked ? "kr_syncbrowse_on" : "kr_syncbrowse_off")); }); syncBrowseButton->setAutoRaise(true); toolbarLayout->addWidget(syncBrowseButton); setButtons(); // create a splitter to hold the view and the popup splt = new PercentalSplitter(clientArea); splt->setChildrenCollapsible(true); splt->setOrientation(Qt::Horizontal); // expand vertical if splitter orientation is horizontal QSizePolicy sizePolicy = splt->sizePolicy(); sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); splt->setSizePolicy(sizePolicy); clientLayout->addWidget(splt); // view createView(); // search (in folder) bar searchBar = new KrSearchBar(view, clientArea); searchBar->hide(); bool top = group.readEntry("Quicksearch Position", "bottom") == "top"; clientLayout->insertWidget(top ? 0 : -1, searchBar); // create the layout KrLayoutFactory fact(this, widgets); QLayout *layout = fact.createLayout(); if(!layout) { // fallback: create a layout by ourself QVBoxLayout *v = new QVBoxLayout; v->setContentsMargins(0, 0, 0, 0); v->setSpacing(0); QHBoxLayout *h = new QHBoxLayout; h->setContentsMargins(0, 0, 0, 0); h->setSpacing(0); h->addWidget(urlNavigator); h->addWidget(toolbar); h->addStretch(); v->addLayout(h); h = new QHBoxLayout; h->setContentsMargins(0, 0, 0, 0); h->setSpacing(0); h->addWidget(mediaButton); h->addWidget(status); h->addWidget(backButton); h->addWidget(forwardButton); h->addWidget(historyButton); h->addWidget(bookmarksButton); v->addLayout(h); v->addWidget(fileSystemError); v->addWidget(clientArea); h = new QHBoxLayout; h->setContentsMargins(0, 0, 0, 0); h->setSpacing(0); h->addWidget(totals); h->addWidget(freeSpace); h->addWidget(quickSizeCalcProgress); h->addWidget(cancelQuickSizeCalcButton); h->addWidget(previewProgress); h->addWidget(cancelProgressButton); h->addWidget(popupBtn); v->addLayout(h); layout = v; } setLayout(layout); connect(&KrColorCache::getColorCache(), SIGNAL(colorsRefreshed()), this, SLOT(refreshColors())); connect(krApp, SIGNAL(shutdown()), SLOT(cancelProgress())); } ListPanel::~ListPanel() { cancelProgress(); delete view; view = 0; delete func; delete status; delete bookmarksButton; delete totals; delete urlNavigator; delete cdRootButton; delete cdHomeButton; delete cdUpButton; delete cdOtherButton; delete syncBrowseButton; // delete layout; } void ListPanel::reparent(QWidget *parent, AbstractPanelManager *manager) { setParent(parent); _manager = manager; } int ListPanel::defaultPanelType() { KConfigGroup group(krConfig, "Look&Feel"); return group.readEntry("Default Panel Type", KrViewFactory::defaultViewId()); } bool ListPanel::isNavigatorEditModeSet() { KConfigGroup group(krConfig, "Look&Feel"); return group.readEntry("Navigator Edit Mode", false); } void ListPanel::createView() { view = KrViewFactory::createView(panelType, splt, krConfig); view->init(); view->setMainWindow(krApp); // KrViewFactory may create a different view type than requested panelType = view->instance()->id(); if(this == ACTIVE_PANEL) view->prepareForActive(); else view->prepareForPassive(); view->refreshColors(); splt->insertWidget(popupPosition() < 2 ? 1 : 0, view->widget()); view->widget()->installEventFilter(this); connect(view->op(), &KrViewOperator::quickCalcSpace, func, &ListPanelFunc::quickCalcSpace); connect(view->op(), SIGNAL(goHome()), func, SLOT(home())); connect(view->op(), SIGNAL(dirUp()), func, SLOT(dirUp())); connect(view->op(), &KrViewOperator::defaultDeleteFiles, func, &ListPanelFunc::defaultDeleteFiles); connect(view->op(), SIGNAL(middleButtonClicked(KrViewItem*)), SLOT(newTab(KrViewItem*))); connect(view->op(), SIGNAL(currentChanged(KrViewItem*)), SLOT(slotCurrentChanged(KrViewItem*))); connect(view->op(), SIGNAL(renameItem(QString,QString)), func, SLOT(rename(QString,QString))); connect(view->op(), SIGNAL(executed(QString)), func, SLOT(execute(QString))); connect(view->op(), SIGNAL(goInside(QString)), func, SLOT(goInside(QString))); connect(view->op(), SIGNAL(needFocus()), this, SLOT(slotFocusOnMe())); connect(view->op(), SIGNAL(selectionChanged()), this, SLOT(slotUpdateTotals())); connect(view->op(), SIGNAL(itemDescription(QString)), krApp, SLOT(statusBarUpdate(QString))); connect(view->op(), SIGNAL(contextMenu(QPoint)), this, SLOT(popRightClickMenu(QPoint))); connect(view->op(), SIGNAL(emptyContextMenu(QPoint)), this, SLOT(popEmptyRightClickMenu(QPoint))); connect(view->op(), SIGNAL(letsDrag(QStringList,QPixmap)), this, SLOT(startDragging(QStringList,QPixmap))); connect(view->op(), &KrViewOperator::gotDrop, this, [this](QDropEvent *event) {handleDrop(event, true); }); connect(view->op(), SIGNAL(previewJobStarted(KJob*)), this, SLOT(slotPreviewJobStarted(KJob*))); connect(view->op(), SIGNAL(refreshActions()), krApp->viewActions(), SLOT(refreshActions())); connect(view->op(), SIGNAL(currentChanged(KrViewItem*)), func->history, SLOT(saveCurrentItem())); connect(view->op(), &KrViewOperator::goBack, func, &ListPanelFunc::historyBackward); connect(view->op(), &KrViewOperator::goForward, func, &ListPanelFunc::historyForward); view->setFiles(func->files()); func->refreshActions(); } void ListPanel::changeType(int type) { if (panelType != type) { QString current = view->getCurrentItem(); QList selection = view->selectedUrls(); bool filterApplysToDirs = view->properties()->filterApplysToDirs; KrViewProperties::FilterSpec filter = view->filter(); FilterSettings filterSettings = view->properties()->filterSettings; panelType = type; KrView *oldView = view; createView(); searchBar->setView(view); delete oldView; view->setFilter(filter, filterSettings, filterApplysToDirs); view->setSelectionUrls(selection); view->setCurrentItem(current); view->makeItemVisible(view->getCurrentKrViewItem()); } } int ListPanel::getProperties() { int props = 0; if (syncBrowseButton->isChecked()) props |= PROP_SYNC_BUTTON_ON; if (_locked) props |= PROP_LOCKED; return props; } void ListPanel::setProperties(int prop) { syncBrowseButton->setChecked(prop & PROP_SYNC_BUTTON_ON); _locked = (prop & PROP_LOCKED); } bool ListPanel::eventFilter(QObject * watched, QEvent * e) { if(view && watched == view->widget()) { if(e->type() == QEvent::FocusIn && this != ACTIVE_PANEL && !isHidden()) slotFocusOnMe(); else if(e->type() == QEvent::ShortcutOverride) { QKeyEvent *ke = static_cast(e); if(ke->key() == Qt::Key_Escape && ke->modifiers() == Qt::NoModifier) { // if the cancel refresh action has no shortcut assigned, // we need this event ourselves to cancel refresh if(_actions->actCancelRefresh->shortcut().isEmpty()) { e->accept(); return true; } } } } // handle URL navigator key events else if(watched == urlNavigator->editor()) { // override default shortcut for panel focus if(e->type() == QEvent::ShortcutOverride) { QKeyEvent *ke = static_cast(e); if ((ke->key() == Qt::Key_Escape) && (ke->modifiers() == Qt::NoModifier)) { e->accept(); // we will get the key press event now return true; } } else if(e->type() == QEvent::KeyPress) { QKeyEvent *ke = static_cast(e); if ((ke->key() == Qt::Key_Down) && (ke->modifiers() == Qt::ControlModifier)) { slotFocusOnMe(); return true; } else if ((ke->key() == Qt::Key_Escape) && (ke->modifiers() == Qt::NoModifier)) { // reset navigator urlNavigator->editor()->setUrl(urlNavigator->locationUrl()); slotFocusOnMe(); return true; } } } return false; } void ListPanel::togglePanelPopup() { if(!popup) { popup = new PanelPopup(splt); // fix vertical grow of splitter (and entire window) if its content // demands more space QSizePolicy sizePolicy = popup->sizePolicy(); sizePolicy.setVerticalPolicy(QSizePolicy::Ignored); popup->setSizePolicy(sizePolicy); connect(this, &ListPanel::pathChanged, popup, &PanelPopup::onPanelPathChange); connect(popup, &PanelPopup::selection, SLOTS, &KRslots::refresh); connect(popup, &PanelPopup::hideMe, this, &ListPanel::togglePanelPopup); splt->insertWidget(0, popup); } if (popup->isHidden()) { if (popupSizes.count() > 0) { splt->setSizes(popupSizes); } else { // on the first time, resize to 50% QList lst; lst << height() / 2 << height() / 2; splt->setSizes(lst); } popup->show(); popupBtn->setIcon(krLoader->loadIcon("arrow-down", KIconLoader::Toolbar, 16)); popupBtn->setToolTip(i18n("Close the popup panel")); popupPositionBtn->show(); } else { popupSizes.clear(); popupSizes = splt->sizes(); popup->hide(); popupBtn->setIcon(krLoader->loadIcon("arrow-up", KIconLoader::Toolbar, 16)); popupBtn->setToolTip(i18n("Open the popup panel")); popupPositionBtn->hide(); QList lst; lst << height() << 0; splt->setSizes(lst); if (ACTIVE_PANEL) ACTIVE_PANEL->gui->slotFocusOnMe(); } } QString ListPanel::lastLocalPath() const { return _lastLocalPath; } void ListPanel::setButtons() { KConfigGroup group(krConfig, "Look&Feel"); mediaButton->setVisible(group.readEntry("Media Button Visible", true)); backButton->setVisible(group.readEntry("Back Button Visible", false)); forwardButton->setVisible(group.readEntry("Forward Button Visible", false)); historyButton->setVisible(group.readEntry("History Button Visible", true)); bookmarksButton->setVisible(group.readEntry("Bookmarks Button Visible", true)); if (group.readEntry("Panel Toolbar visible", _PanelToolBar)) { cdRootButton->setVisible(group.readEntry("Root Button Visible", _cdRoot)); cdHomeButton->setVisible(group.readEntry("Home Button Visible", _cdHome)); cdUpButton->setVisible(group.readEntry("Up Button Visible", _cdUp)); cdOtherButton->setVisible(group.readEntry("Equal Button Visible", _cdOther)); syncBrowseButton->setVisible(group.readEntry("SyncBrowse Button Visible", _syncBrowseButton)); } else { cdRootButton->hide(); cdHomeButton->hide(); cdUpButton->hide(); cdOtherButton->hide(); syncBrowseButton->hide(); } } void ListPanel::slotUpdateTotals() { totals->setText(view->statistics()); } void ListPanel::compareDirs(bool otherPanelToo) { // Performs a check in order to avoid that the next code is executed twice if (otherPanelToo == true) { // If both panels are showing the same directory if (_manager->currentPanel()->virtualPath() == otherPanel()->virtualPath()) { if (KMessageBox::warningContinueCancel(this, i18n("Warning: The left and the right side are showing the same folder.")) != KMessageBox::Continue) { return; } } } KConfigGroup pg(krConfig, "Private"); int compareMode = pg.readEntry("Compare Mode", 0); KConfigGroup group(krConfig, "Look&Feel"); bool selectDirs = group.readEntry("Mark Dirs", false); KrViewItem *item, *otherItem; for (item = view->getFirst(); item != 0; item = view->getNext(item)) { if (item->name() == "..") continue; for (otherItem = otherPanel()->view->getFirst(); otherItem != 0 && otherItem->name() != item->name() ; otherItem = otherPanel()->view->getNext(otherItem)); bool isSingle = (otherItem == 0), isDifferent = false, isNewer = false; if (func->getFileItem(item)->isDir() && !selectDirs) { item->setSelected(false); continue; } if (otherItem) { if (!func->getFileItem(item)->isDir()) isDifferent = otherPanel()->func->getFileItem(otherItem)->getSize() != func->getFileItem(item)->getSize(); isNewer = func->getFileItem(item)->getTime_t() > otherPanel()->func->getFileItem(otherItem)->getTime_t(); } switch (compareMode) { case 0: item->setSelected(isNewer || isSingle); break; case 1: item->setSelected(isNewer); break; case 2: item->setSelected(isSingle); break; case 3: item->setSelected(isDifferent || isSingle); break; case 4: item->setSelected(isDifferent); break; } } view->updateView(); if (otherPanelToo) otherPanel()->gui->compareDirs(false); } void ListPanel::refreshColors() { view->refreshColors(); emit refreshColors(this == ACTIVE_PANEL); } void ListPanel::slotFocusOnMe(bool focus) { if (focus && _manager->currentPanel() != this) { // ignore focus request if this panel is not shown return; } krApp->setUpdatesEnabled(false); if(focus) { emit activate(); _actions->activePanelChanged(); func->refreshActions(); slotCurrentChanged(view->getCurrentKrViewItem()); view->prepareForActive(); otherPanel()->gui->slotFocusOnMe(false); } else { // in case a new url was entered but not refreshed to, // reset url navigator to the current url setNavigatorUrl(virtualPath()); view->prepareForPassive(); } urlNavigator->setActive(focus); refreshColors(); krApp->setUpdatesEnabled(true); } // this is used to start the panel ////////////////////////////////////////////////////////////////// void ListPanel::start(const QUrl &url) { QUrl startUrl(url); if (!startUrl.isValid()) startUrl = QUrl::fromLocalFile(ROOT_DIR); _lastLocalPath = startUrl.isLocalFile() ? startUrl.path() : ROOT_DIR; func->openUrl(startUrl); setJumpBack(startUrl); } void ListPanel::slotStartUpdate(bool directoryChange) { if (inlineRefreshJob) inlineRefreshListResult(0); setCursor(Qt::BusyCursor); const QUrl currentUrl = virtualPath(); if (directoryChange) { if (this == ACTIVE_PANEL) { slotFocusOnMe(); } if (currentUrl.isLocalFile()) _lastLocalPath = currentUrl.path(); setNavigatorUrl(currentUrl); emit pathChanged(currentUrl); krApp->popularUrls()->addUrl(currentUrl); searchBar->hideBar(); } if (compareMode) otherPanel()->view->refresh(); // return cursor to normal arrow setCursor(Qt::ArrowCursor); slotUpdateTotals(); } void ListPanel::updateFilesystemStats(const QString &metaInfo, const QString &fsType, KIO::filesize_t total, KIO::filesize_t free) { QString statusText, mountPoint, freeSpaceText; if (!metaInfo.isEmpty()) { statusText = metaInfo; mountPoint = freeSpaceText = ""; } else { const int perc = total == 0 ? 0 : (int)(((float)free / (float)total) * 100.0); mountPoint = func->files()->mountPoint(); statusText = i18nc("%1=free space,%2=total space,%3=percentage of usage, " "%4=mountpoint,%5=filesystem type", "%1 free out of %2 (%3%) on %4 [(%5)]", KIO::convertSize(free), KIO::convertSize(total), perc, mountPoint, fsType); freeSpaceText = " " + i18n("%1 free", KIO::convertSize(free)); } status->setText(statusText); freeSpace->setText(freeSpaceText); mediaButton->updateIcon(mountPoint); } void ListPanel::handleDrop(QDropEvent *event, bool onView) { // check what was dropped const QList urls = KUrlMimeData::urlsFromMimeData(event->mimeData()); if (urls.isEmpty()) { event->ignore(); // not for us to handle! return; } // find dropping destination QString destinationDir = ""; const bool dragFromThisPanel = event->source() == this; const KrViewItem *item = onView ? view->getKrViewItemAt(event->pos()) : 0; if (item) { const FileItem *file = item->getFileItem(); if (file && !file->isDir() && dragFromThisPanel) { event->ignore(); // dragging on files in same panel, ignore return ; } else if (!file || file->isDir()) { // item is ".." dummy or a directory destinationDir = item->name(); } } else if (dragFromThisPanel) { event->ignore(); // dragged from this panel onto an empty spot in this panel, ignore return ; } QUrl destination = QUrl(virtualPath()); destination.setPath(destination.path() + '/' + destinationDir); func->files()->dropFiles(destination, event); if(KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { KrPanel *p = dragFromThisPanel ? this : otherPanel(); p->view->saveSelection(); p->view->unselectAll(); } } void ListPanel::handleDrop(const QUrl &destination, QDropEvent *event) { func->files()->dropFiles(destination, event); } void ListPanel::startDragging(QStringList names, QPixmap px) { if (names.isEmpty()) { // avoid dragging empty urls return; } QList urls = func->files()->getUrls(names); QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; drag->setPixmap(px); mimeData->setUrls(urls); drag->setMimeData(mimeData); drag->start(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction); } // pops a right-click menu for items void ListPanel::popRightClickMenu(const QPoint &loc) { // run it, on the mouse location int j = QFontMetrics(font()).height() * 2; KrPopupMenu::run(QPoint(loc.x() + 5, loc.y() + j), this); } void ListPanel::popEmptyRightClickMenu(const QPoint &loc) { KrPopupMenu::run(loc, this); } QString ListPanel::getCurrentName() { QString name = view->getCurrentItem(); if (name != "..") return name; else return QString(); } QStringList ListPanel::getSelectedNames() { QStringList fileNames; view->getSelectedItems(&fileNames); return fileNames; } void ListPanel::prepareToDelete() { view->setNameToMakeCurrent(view->firstUnmarkedBelowCurrent()); } void ListPanel::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Enter : case Qt::Key_Return : if (e->modifiers() & Qt::ControlModifier) { if (e->modifiers() & Qt::AltModifier) { FileItem *fileitem = func->files()->getFileItem(view->getCurrentKrViewItem()->name()); if (fileitem && fileitem->isDir()) newTab(fileitem->getUrl(), true); } else { SLOTS->insertFileName((e->modifiers() & Qt::ShiftModifier) != 0); } } else { e->ignore(); } break; case Qt::Key_Right : case Qt::Key_Left : if (e->modifiers() == Qt::ControlModifier) { // user pressed CTRL+Right/Left - refresh other panel to the selected path if it's a // directory otherwise as this one if ((isLeft() && e->key() == Qt::Key_Right) || (!isLeft() && e->key() == Qt::Key_Left)) { QUrl newPath; KrViewItem *it = view->getCurrentKrViewItem(); if (it->name() == "..") { newPath = KIO::upUrl(virtualPath()); } else { FileItem *v = func->getFileItem(it); // If it's a directory different from ".." if (v && v->isDir() && v->getName() != "..") { newPath = v->getUrl(); } else { // If it's a supported compressed file if (v && KRarcHandler::arcSupported(v->getMime())) { newPath = func->browsableArchivePath(v->getUrl().fileName()); } else { newPath = virtualPath(); } } } otherPanel()->func->openUrl(newPath); } else { func->openUrl(otherPanel()->virtualPath()); } return ; } else e->ignore(); break; case Qt::Key_Down : if (e->modifiers() == Qt::ControlModifier) { // give the keyboard focus to the command line if (MAIN_VIEW->cmdLine()->isVisible()) MAIN_VIEW->cmdLineFocus(); else MAIN_VIEW->focusTerminalEmulator(); return ; } else if (e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { // give the keyboard focus to TE MAIN_VIEW->focusTerminalEmulator(); } else e->ignore(); break; case Qt::Key_Up : if (e->modifiers() == Qt::ControlModifier) { // give the keyboard focus to the url navigator editLocation(); return ; } else e->ignore(); break; case Qt::Key_Escape: cancelProgress(); break; default: // if we got this, it means that the view is not doing // the quick search thing, so send the characters to the commandline, if normal key if (e->modifiers() == Qt::NoModifier) MAIN_VIEW->cmdLine()->addText(e->text()); //e->ignore(); } } void ListPanel::showEvent(QShowEvent *e) { panelVisible(); QWidget::showEvent(e); } void ListPanel::hideEvent(QHideEvent *e) { panelHidden(); QWidget::hideEvent(e); } void ListPanel::panelVisible() { func->setPaused(false); } void ListPanel::panelHidden() { func->setPaused(true); } void ListPanel::slotPreviewJobStarted(KJob *job) { previewJob = job; connect(job, SIGNAL(percent(KJob*,ulong)), SLOT(slotPreviewJobPercent(KJob*,ulong))); connect(job, &KJob::result, this, &ListPanel::slotPreviewJobResult); cancelProgressButton->setMaximumHeight(popupBtn->height()); cancelProgressButton->show(); previewProgress->setValue(0); previewProgress->setFormat(i18n("loading previews: %p%")); previewProgress->setMaximumHeight(cancelProgressButton->height()); previewProgress->show(); } void ListPanel::slotPreviewJobPercent(KJob* /*job*/, unsigned long percent) { previewProgress->setValue(percent); } void ListPanel::slotPreviewJobResult(KJob* /*job*/) { previewJob = 0; previewProgress->hide(); if(!inlineRefreshJob) cancelProgressButton->hide(); } void ListPanel::slotRefreshJobStarted(KIO::Job* job) { // disable the parts of the panel we don't want touched status->setEnabled(false); urlNavigator->setEnabled(false); cdRootButton->setEnabled(false); cdHomeButton->setEnabled(false); cdUpButton->setEnabled(false); cdOtherButton->setEnabled(false); popupBtn->setEnabled(false); if(popup) popup->setEnabled(false); bookmarksButton->setEnabled(false); historyButton->setEnabled(false); syncBrowseButton->setEnabled(false); // connect to the job interface to provide in-panel refresh notification connect(job, SIGNAL(infoMessage(KJob*,QString)), SLOT(inlineRefreshInfoMessage(KJob*,QString))); connect(job, SIGNAL(percent(KJob*,ulong)), SLOT(inlineRefreshPercent(KJob*,ulong))); connect(job, SIGNAL(result(KJob*)), this, SLOT(inlineRefreshListResult(KJob*))); inlineRefreshJob = job; totals->setText(i18n(">> Reading...")); cancelProgressButton->show(); } void ListPanel::cancelProgress() { if (inlineRefreshJob) { disconnect(inlineRefreshJob, 0, this, 0); inlineRefreshJob->kill(KJob::EmitResult); inlineRefreshListResult(0); } if(previewJob) { disconnect(previewJob, 0, this, 0); previewJob->kill(KJob::EmitResult); slotPreviewJobResult(0); } } void ListPanel::setNavigatorUrl(const QUrl &url) { _navigatorUrl = url; urlNavigator->setLocationUrl(url); } void ListPanel::inlineRefreshPercent(KJob*, unsigned long perc) { QString msg = i18n(">> Reading: %1 % complete...", perc); totals->setText(msg); } void ListPanel::inlineRefreshInfoMessage(KJob*, const QString &msg) { totals->setText(i18n(">> Reading: %1", msg)); } void ListPanel::inlineRefreshListResult(KJob*) { if(inlineRefreshJob) disconnect(inlineRefreshJob, 0, this, 0); inlineRefreshJob = 0; // reenable everything status->setEnabled(true); urlNavigator->setEnabled(true); cdRootButton->setEnabled(true); cdHomeButton->setEnabled(true); cdUpButton->setEnabled(true); cdOtherButton->setEnabled(true); popupBtn->setEnabled(true); if(popup) popup->setEnabled(true); bookmarksButton->setEnabled(true); historyButton->setEnabled(true); syncBrowseButton->setEnabled(true); if(!previewJob) cancelProgressButton->hide(); } void ListPanel::jumpBack() { func->openUrl(_jumpBackURL); } void ListPanel::setJumpBack(QUrl url) { _jumpBackURL = url; } void ListPanel::slotFilesystemError(QString msg) { refreshColors(); fileSystemError->setText(i18n("Error: %1", msg)); fileSystemError->show(); } void ListPanel::showButtonMenu(QToolButton *b) { if(this != ACTIVE_PANEL) slotFocusOnMe(); if(b->isHidden()) b->menu()->exec(mapToGlobal(clientArea->pos())); else b->click(); } void ListPanel::openBookmarks() { showButtonMenu(bookmarksButton); } void ListPanel::openHistory() { showButtonMenu(historyButton); } void ListPanel::openMedia() { showButtonMenu(mediaButton); } void ListPanel::rightclickMenu() { if (view->getCurrentKrViewItem()) popRightClickMenu(mapToGlobal(view->getCurrentKrViewItem()->itemRect().topLeft())); } void ListPanel::toggleSyncBrowse() { syncBrowseButton->toggle(); } void ListPanel::editLocation() { urlNavigator->setUrlEditable(true); urlNavigator->setFocus(); urlNavigator->editor()->lineEdit()->selectAll(); } void ListPanel::showSearchBar() { searchBar->showBar(); } void ListPanel::showSearchFilter() { searchBar->showBar(KrSearchBar::MODE_FILTER); } void ListPanel::saveSettings(KConfigGroup cfg, bool saveHistory) { QUrl url = virtualPath(); url.setPassword(QString()); // make sure no password is saved cfg.writeEntry("Url", url.toString()); cfg.writeEntry("Type", getType()); cfg.writeEntry("Properties", getProperties()); if(saveHistory) func->history->save(KConfigGroup(&cfg, "History")); view->saveSettings(KConfigGroup(&cfg, "View")); // splitter/popup state if (popup && !popup->isHidden()) { popup->saveSettings(KConfigGroup(&cfg, "PanelPopup")); cfg.writeEntry("PopupPosition", popupPosition()); cfg.writeEntry("SplitterSizes", splt->saveState()); cfg.writeEntry("PopupPage", popup->currentPage()); } else { cfg.deleteEntry("PopupPosition"); cfg.deleteEntry("SplitterSizes"); cfg.deleteEntry("PopupPage"); } } void ListPanel::restoreSettings(KConfigGroup cfg) { changeType(cfg.readEntry("Type", defaultPanelType())); view->restoreSettings(KConfigGroup(&cfg, "View")); // "locked" property must be set after URL path is restored! // This panel can be reused when loading a profile, // so we reset its properties before calling openUrl(). setProperties(0); _lastLocalPath = ROOT_DIR; if(func->history->restore(KConfigGroup(&cfg, "History"))) { func->refresh(); } else { QUrl url(cfg.readEntry("Url", "invalid")); if (!url.isValid()) url = QUrl::fromLocalFile(ROOT_DIR); func->openUrl(url); } setJumpBack(func->history->currentUrl()); setProperties(cfg.readEntry("Properties", 0)); if (cfg.hasKey("PopupPosition")) { // popup was visible, restore togglePanelPopup(); // create and show popup->restoreSettings(KConfigGroup(&cfg, "PanelPopup")); setPopupPosition(cfg.readEntry("PopupPosition", 42 /* dummy */)); splt->restoreState(cfg.readEntry("SplitterSizes", QByteArray())); popup->setCurrentPage(cfg.readEntry("PopupPage", 0)); } } void ListPanel::slotCurrentChanged(KrViewItem *item) { // update status bar if (item) krApp->statusBarUpdate(item->description()); // update popup panel; which panel to display on? PanelPopup *p; if(popup && !popup->isHidden()) p = popup; else if(otherPanel()->gui->popup && !otherPanel()->gui->popup->isHidden()) p = otherPanel()->gui->popup; else return; p->update(item ? func->files()->getFileItem(item->name()) : 0); } void ListPanel::otherPanelChanged() { func->syncURL = QUrl(); } void ListPanel::getFocusCandidates(QVector &widgets) { if(urlNavigator->editor()->isVisible()) widgets << urlNavigator->editor(); if(view->widget()->isVisible()) widgets << view->widget(); if(popup && popup->isVisible()) widgets << popup; } void ListPanel::updateButtons() { backButton->setEnabled(func->history->canGoBack()); forwardButton->setEnabled(func->history->canGoForward()); historyButton->setEnabled(func->history->count() > 1); cdRootButton->setEnabled(!virtualPath().matches(QUrl::fromLocalFile(ROOT_DIR), QUrl::StripTrailingSlash)); cdUpButton->setEnabled(!func->files()->isRoot()); cdHomeButton->setEnabled(!func->atHome()); } void ListPanel::newTab(KrViewItem *it) { if (!it) return; else if (it->name() == "..") { newTab(KIO::upUrl(virtualPath()), true); } else if (func->getFileItem(it)->isDir()) { QUrl url = virtualPath(); url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (it->name())); newTab(url, true); } } void ListPanel::newTab(const QUrl &url, bool nextToThis) { _manager->newTab(url, nextToThis ? this : 0); } void ListPanel::slotNavigatorUrlChanged(const QUrl &url) { if (url == _navigatorUrl) return; // this is the URL we just set ourself if (!isNavigatorEditModeSet()) { urlNavigator->setUrlEditable(false); } func->openUrl(KrServices::escapeFileUrl(url), QString(), true); } void ListPanel::resetNavigatorMode() { if (isNavigatorEditModeSet()) return; // set to "navigate" mode if url wasn't changed if (urlNavigator->uncommittedUrl().matches(virtualPath(), QUrl::StripTrailingSlash)) { // NOTE: this also sets focus to the navigator urlNavigator->setUrlEditable(false); slotFocusOnMe(); } } int ListPanel::popupPosition() const { int pos = splt->orientation() == Qt::Vertical ? 1 : 0; return pos + (qobject_cast(splt->widget(0)) == NULL ? 2 : 0); } void ListPanel::setPopupPosition(int pos) { splt->setOrientation(pos % 2 == 0 ? Qt::Horizontal : Qt::Vertical); if ((pos < 2) != (qobject_cast(splt->widget(0)) != NULL)) { splt->insertWidget(0, splt->widget(1)); // swapping widgets in splitter } } void ListPanel::connectQuickSizeCalculator(SizeCalculator *sizeCalculator) { connect(sizeCalculator, &SizeCalculator::started, this, [=]() { quickSizeCalcProgress->reset(); quickSizeCalcProgress->show(); cancelQuickSizeCalcButton->show(); }); connect(cancelQuickSizeCalcButton, &QToolButton::clicked, sizeCalculator, &SizeCalculator::cancel); connect(sizeCalculator, &SizeCalculator::progressChanged, quickSizeCalcProgress, &QProgressBar::setValue); connect(sizeCalculator, &SizeCalculator::finished, this, [=]() { cancelQuickSizeCalcButton->hide(); quickSizeCalcProgress->hide(); }); } diff --git a/krusader/Panel/listpanelactions.cpp b/krusader/Panel/listpanelactions.cpp index a5f7cc06..9a408d2b 100644 --- a/krusader/Panel/listpanelactions.cpp +++ b/krusader/Panel/listpanelactions.cpp @@ -1,216 +1,216 @@ /*************************************************************************** listpanelactions.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai copyright : (C) 2010 by Jan Lepper e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "listpanelactions.h" #include "listpanel.h" #include "panelfunc.h" -#include "krviewfactory.h" +#include "PanelView/krviewfactory.h" #include "../krmainwindow.h" #include "../Dialogs/krdialogs.h" #include "../KViewer/krviewer.h" // QtCore #include // QtWidgets #include #include #include ListPanelActions::ListPanelActions(QObject *parent, KrMainWindow *mainWindow) : ActionsBase(parent, mainWindow) { // set view type QSignalMapper *mapper = new QSignalMapper(this); connect(mapper, SIGNAL(mapped(int)), SLOT(setView(int))); QActionGroup *group = new QActionGroup(this); group->setExclusive(true); QList views = KrViewFactory::registeredViews(); for(int i = 0; i < views.count(); i++) { KrViewInstance *inst = views[i]; QAction *action = new QAction(QIcon::fromTheme(inst->icon()), inst->description(), group); action->setCheckable(true); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); mapper->setMapping(action, inst->id()); _mainWindow->actions()->addAction("view" + QString::number(i), action); _mainWindow->actions()->setDefaultShortcut(action, inst->shortcut()); setViewActions.insert(inst->id(), action); } // standard actions actHistoryBackward = stdAction(KStandardAction::Back, _func, SLOT(historyBackward())); actHistoryForward = stdAction(KStandardAction::Forward, _func, SLOT(historyForward())); //FIXME: second shortcut for up: see actDirUp // KStandardAction::up( this, SLOT(dirUp()), actionCollection )->setShortcut(Qt::Key_Backspace); /* Shortcut disabled because of the Terminal Emulator bug. */ actDirUp = stdAction(KStandardAction::Up, _func, SLOT(dirUp())); actHome = stdAction(KStandardAction::Home, _func, SLOT(home())); stdAction(KStandardAction::Cut, _func, SLOT(cut())); actCopy = stdAction(KStandardAction::Copy, _func, SLOT(copyToClipboard())); actPaste = stdAction(KStandardAction::Paste, _func, SLOT(pasteFromClipboard())); // Fn keys actF2 = action(i18n("Rename"), 0, Qt::Key_F2, _func, SLOT(rename()) , "F2_Rename"); actF3 = action(i18n("View File"), 0, Qt::Key_F3, _func, SLOT(view()), "F3_View"); actF4 = action(i18n("Edit File"), 0, Qt::Key_F4, _func, SLOT(edit()) , "F4_Edit"); actF5 = action(i18n("Copy to other panel"), 0, Qt::Key_F5, _func, SLOT(copyFiles()) , "F5_Copy"); actF6 = action(i18n("Move..."), 0, Qt::Key_F6, _func, SLOT(moveFiles()) , "F6_Move"); actShiftF5 = action(i18n("Copy delayed..."), 0, Qt::SHIFT + Qt::Key_F5, _func, SLOT(copyFilesDelayed()) , "F5_Copy_Queue"); actShiftF6 = action(i18n("Move delayed..."), 0, Qt::SHIFT + Qt::Key_F6, _func, SLOT(moveFilesDelayed()) , "F6_Move_Queue"); actF7 = action(i18n("New Folder..."), "folder-new", Qt::Key_F7, _func, SLOT(mkdir()) , "F7_Mkdir"); actF8 = action(i18n("Delete"), "edit-delete", Qt::Key_F8, _func, SLOT(defaultDeleteFiles()) , "F8_Delete"); actF9 = action(i18n("Start Terminal Here"), "utilities-terminal", Qt::Key_F9, _func, SLOT(terminal()) , "F9_Terminal"); action(i18n("&New Text File..."), "document-new", Qt::SHIFT + Qt::Key_F4, _func, SLOT(editNew()), "edit_new_file"); action(i18n("F3 View Dialog"), 0, Qt::SHIFT + Qt::Key_F3, _func, SLOT(viewDlg()), "F3_ViewDlg"); // file operations action(i18n("Right-click Menu"), 0, Qt::Key_Menu, _gui, SLOT(rightclickMenu()), "rightclick menu"); actProperties = action(i18n("&Properties..."), "document-properties", Qt::ALT + Qt::Key_Return, _func, SLOT(properties()), "properties"); actCompDirs = action(i18n("&Compare Folders"), "kr_comparedirs", Qt::ALT + Qt::SHIFT + Qt::Key_C, _gui, SLOT(compareDirs()), "compare dirs"); actCalculate = action(i18n("Calculate &Occupied Space"), "accessories-calculator", 0, _func, SLOT(calcSpace()), "calculate"); actPack = action(i18n("Pac&k..."), "archive-insert", Qt::ALT + Qt::SHIFT + Qt::Key_P, _func, SLOT(pack()), "pack"); actUnpack = action(i18n("&Unpack..."), "archive-extract", Qt::ALT + Qt::SHIFT + Qt::Key_U, _func, SLOT(unpack()), "unpack"); actCreateChecksum = action(i18n("Create Checksum..."), "document-edit-sign", 0, _func, SLOT(createChecksum()), "create checksum"); actMatchChecksum = action(i18n("Verify Checksum..."), "document-edit-decrypt-verify", 0, _func, SLOT(matchChecksum()), "match checksum"); action(i18n("New Symlink..."), 0, Qt::CTRL + Qt::ALT + Qt::Key_S, _func, SLOT(krlink()), "new symlink"); actTest = action(i18n("T&est Archive"), "archive-extract", Qt::ALT + Qt::SHIFT + Qt::Key_E, _func, SLOT(testArchive()), "test archives"); // navigation actRoot = action(i18n("Root"), "folder-red", Qt::CTRL + Qt::Key_Backspace, _func, SLOT(root()), "root"); actCdToOther = action(i18n("Go to Other Panel's Folder"), 0, Qt::CTRL + Qt::Key_Equal, _func, SLOT(cdToOtherPanel()), "cd to other panel"); action(i18n("&Reload"), "view-refresh", Qt::CTRL + Qt::Key_R, _func, SLOT(refresh()), "std_redisplay"); actCancelRefresh = action(i18n("Cancel Refresh of View"), "dialog-cancel", 0, _gui, SLOT(cancelProgress()), "cancel refresh"); actFTPNewConnect = action(i18n("New Net &Connection..."), "network-connect", Qt::CTRL + Qt::Key_N, _func, SLOT(newFTPconnection()), "ftp new connection"); actFTPDisconnect = action(i18n("Disconnect &from Net"), "network-disconnect", Qt::SHIFT + Qt::CTRL + Qt::Key_D, _func, SLOT(FTPDisconnect()), "ftp disconnect"); action(i18n("Sync Panels"), 0, Qt::ALT + Qt::SHIFT + Qt::Key_O, _func, SLOT(syncOtherPanel()), "sync panels"); actJumpBack = action(i18n("Jump Back"), "go-jump", Qt::CTRL + Qt::Key_J, _gui, SLOT(jumpBack()), "jump_back"); actSetJumpBack = action(i18n("Set Jump Back Point"), "go-jump-definition", Qt::CTRL + Qt::SHIFT + Qt::Key_J, _gui, SLOT(setJumpBack()), "set_jump_back"); actSyncBrowse = action(i18n("S&ynchron Folder Changes"), "kr_syncbrowse_off", Qt::ALT + Qt::SHIFT + Qt::Key_Y, _gui, SLOT(toggleSyncBrowse()), "sync browse"); actLocationBar = action(i18n("Go to Location Bar"), 0, Qt::CTRL + Qt::Key_L, _gui, SLOT(editLocation()), "location_bar"); actSearchBar = action(i18n("Find in folder..."), 0, Qt::CTRL + Qt::Key_F, _gui, SLOT(showSearchBar()), "search bar"); action(i18n("Open search filter"), 0, Qt::CTRL + Qt::Key_I, _gui, SLOT(showSearchFilter()), "search bar filter"); toggleAction(i18n("Toggle Popup Panel"), 0, Qt::ALT + Qt::Key_Down, _gui, SLOT(togglePanelPopup()), "toggle popup panel"); action(i18n("Bookmarks"), 0, Qt::CTRL + Qt::Key_D, _gui, SLOT(openBookmarks()), "bookmarks"); action(i18n("Left Bookmarks"), 0, 0, this, SLOT(openLeftBookmarks()), "left bookmarks"); action(i18n("Right Bookmarks"), 0, 0, this, SLOT(openRightBookmarks()), "right bookmarks"); action(i18n("History"), 0, Qt::CTRL + Qt::Key_H, _gui, SLOT(openHistory()), "history"); action(i18n("Left History"), 0, Qt::ALT + Qt::CTRL + Qt::Key_Left, this, SLOT(openLeftHistory()), "left history"); action(i18n("Right History"), 0, Qt::ALT + Qt::CTRL + Qt::Key_Right, this, SLOT(openRightHistory()), "right history"); action(i18n("Media"), 0, Qt::CTRL + Qt::Key_M, _gui, SLOT(openMedia()), "media"); action(i18n("Left Media"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Left, this, SLOT(openLeftMedia()), "left media"); action(i18n("Right Media"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Right, this, SLOT(openRightMedia()), "right media"); // and at last we can set the tool-tips actRoot->setToolTip(i18n("ROOT (/)")); actF2->setToolTip(i18n("Rename file, folder, etc.")); actF3->setToolTip(i18n("Open file in viewer.")); actF4->setToolTip(i18n("

Edit file.

" "

The editor can be defined in Konfigurator, " "default is internal editor.

")); actF5->setToolTip(i18n("Copy file from one panel to the other.")); actF6->setToolTip(i18n("Move file from one panel to the other.")); actF7->setToolTip(i18n("Create folder in current panel.")); actF8->setToolTip(i18n("Delete file, folder, etc.")); actF9->setToolTip(i18n("

Open terminal in current folder.

" "

The terminal can be defined in Konfigurator, " "default is konsole.

")); } void ListPanelActions::activePanelChanged() { _gui.reconnect(activePanel()->gui); _func.reconnect(activePanel()->func); } void ListPanelActions::guiUpdated() { QList actions; foreach(QAction *action, setViewActions.values()) actions << action; static_cast(_mainWindow)->plugActionList("view_actionlist", actions); } inline KrPanel *ListPanelActions::activePanel() { return static_cast(_mainWindow)->activePanel(); } inline KrPanel *ListPanelActions::leftPanel() { return static_cast(_mainWindow)->leftPanel(); } inline KrPanel *ListPanelActions::rightPanel() { return static_cast(_mainWindow)->rightPanel(); } // set view type void ListPanelActions::setView(int id) { activePanel()->gui->changeType(id); } // navigation void ListPanelActions::openLeftBookmarks() { leftPanel()->gui->openBookmarks(); } void ListPanelActions::openRightBookmarks() { rightPanel()->gui->openBookmarks(); } void ListPanelActions::openLeftHistory() { leftPanel()->gui->openHistory(); } void ListPanelActions::openRightHistory() { rightPanel()->gui->openHistory(); } void ListPanelActions::openLeftMedia() { leftPanel()->gui->openMedia(); } void ListPanelActions::openRightMedia() { rightPanel()->gui->openMedia(); } diff --git a/krusader/Panel/panelfunc.cpp b/krusader/Panel/panelfunc.cpp index 04a161bd..eccc7491 100644 --- a/krusader/Panel/panelfunc.cpp +++ b/krusader/Panel/panelfunc.cpp @@ -1,1270 +1,1270 @@ /*************************************************************************** panelfunc.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "panelfunc.h" // QtCore #include #include #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dirhistoryqueue.h" #include "krcalcspacedialog.h" #include "krerrordisplay.h" -#include "krview.h" -#include "krviewitem.h" #include "listpanel.h" #include "listpanelactions.h" +#include "PanelView/krview.h" +#include "PanelView/krviewitem.h" #include "../krglobal.h" #include "../krslots.h" #include "../kractions.h" #include "../defaults.h" #include "../abstractpanelmanager.h" #include "../krservices.h" #include "../Archive/krarchandler.h" #include "../Archive/packjob.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/virtualfilesystem.h" #include "../FileSystem/krpermhandler.h" #include "../FileSystem/filesystemprovider.h" #include "../FileSystem/sizecalculator.h" #include "../Dialogs/packgui.h" #include "../Dialogs/krdialogs.h" #include "../Dialogs/krpleasewait.h" #include "../Dialogs/krspwidgets.h" #include "../Dialogs/checksumdlg.h" #include "../KViewer/krviewer.h" #include "../MountMan/kmountman.h" QPointer ListPanelFunc::copyToClipboardOrigin; ListPanelFunc::ListPanelFunc(ListPanel *parent) : QObject(parent), panel(parent), fileSystemP(0), urlManuallyEntered(false), _isPaused(true), _refreshAfterPaused(true), _quickSizeCalculator(0) { history = new DirHistoryQueue(panel); delayTimer.setSingleShot(true); connect(&delayTimer, SIGNAL(timeout()), this, SLOT(doRefresh())); } ListPanelFunc::~ListPanelFunc() { if (fileSystemP) { fileSystemP->deleteLater(); } delete history; if (_quickSizeCalculator) _quickSizeCalculator->deleteLater(); } bool ListPanelFunc::isSyncing(const QUrl &url) { if(otherFunc()->otherFunc() == this && panel->otherPanel()->gui->syncBrowseButton->isChecked() && !otherFunc()->syncURL.isEmpty() && otherFunc()->syncURL == url) return true; return false; } void ListPanelFunc::openFileNameInternal(const QString &name, bool externallyExecutable) { if (name == "..") { dirUp(); return ; } FileItem *fileitem = files()->getFileItem(name); if (fileitem == 0) return ; QUrl url = files()->getUrl(name); if (fileitem->isDir()) { panel->view->setNameToMakeCurrent(QString()); openUrl(url); return; } QString mime = fileitem->getMime(); QUrl arcPath = browsableArchivePath(name); if (!arcPath.isEmpty()) { bool browseAsDirectory = !externallyExecutable || (KConfigGroup(krConfig, "Archives").readEntry("ArchivesAsDirectories", _ArchivesAsDirectories) && (KRarcHandler::arcSupported(mime) || KrServices::isoSupported(mime))); if (browseAsDirectory) { openUrl(arcPath); return; } } if (externallyExecutable) { if (KRun::isExecutableFile(url, mime)) { runCommand(KShell::quoteArg(url.path())); return; } KService::Ptr service = KMimeTypeTrader::self()->preferredService(mime); if(service) { runService(*service, QList() << url); return; } displayOpenWithDialog(QList() << url); } } QUrl ListPanelFunc::cleanPath(const QUrl &urlIn) { QUrl url = urlIn; url.setPath(QDir::cleanPath(url.path())); if (!url.isValid() || url.isRelative()) { if (url.url() == "~") url = QUrl::fromLocalFile(QDir::homePath()); else if (!url.url().startsWith('/')) { // possible relative URL - translate to full URL url = files()->currentDirectory(); url.setPath(url.path() + '/' + urlIn.path()); } } url.setPath(QDir::cleanPath(url.path())); return url; } void ListPanelFunc::openUrl(const QUrl &url, const QString& nameToMakeCurrent, bool manuallyEntered) { if (panel->syncBrowseButton->isChecked()) { //do sync-browse stuff.... if(syncURL.isEmpty()) syncURL = panel->otherPanel()->virtualPath(); QString relative = QDir(panel->virtualPath().path() + '/').relativeFilePath(url.path()); syncURL.setPath(QDir::cleanPath(syncURL.path() + '/' + relative)); panel->otherPanel()->gui->setLocked(false); otherFunc()->openUrlInternal(syncURL, nameToMakeCurrent, false, false); } openUrlInternal(url, nameToMakeCurrent, false, manuallyEntered); } void ListPanelFunc::immediateOpenUrl(const QUrl &url) { openUrlInternal(url, QString(), true, false); } void ListPanelFunc::openUrlInternal(const QUrl &url, const QString& nameToMakeCurrent, bool immediately, bool manuallyEntered) { const QUrl cleanUrl = cleanPath(url); if (panel->isLocked() && !files()->currentDirectory().matches(cleanUrl, QUrl::StripTrailingSlash)) { panel->_manager->newTab(url); urlManuallyEntered = false; return; } urlManuallyEntered = manuallyEntered; history->add(cleanUrl, nameToMakeCurrent); if(immediately) doRefresh(); else refresh(); } void ListPanelFunc::refresh() { panel->cancelProgress(); delayTimer.start(0); // to avoid qApp->processEvents() deadlock situaltion } void ListPanelFunc::doRefresh() { delayTimer.stop(); if (_isPaused) { _refreshAfterPaused = true; // simulate refresh panel->slotStartUpdate(true); return; } else { _refreshAfterPaused = false; } const QUrl url = history->currentUrl(); if(!url.isValid()) { panel->slotStartUpdate(true); // refresh the panel urlManuallyEntered = false; return ; } panel->cancelProgress(); // if we are not refreshing to current URL const bool isEqualUrl = files()->currentDirectory().matches(url, QUrl::StripTrailingSlash); if (!isEqualUrl) { panel->setCursor(Qt::WaitCursor); panel->view->clearSavedSelection(); } if (panel->fileSystemError) { panel->fileSystemError->hide(); } panel->setNavigatorUrl(url); // may get a new filesystem for this url FileSystem *fileSystem = FileSystemProvider::instance().getFilesystem(url, files()); fileSystem->setParentWindow(krMainWindow); connect(fileSystem, &FileSystem::aboutToOpenDir, &krMtMan, &KMountMan::autoMount, Qt::DirectConnection); if (fileSystem != fileSystemP) { panel->view->setFiles(0); // disconnect older signals disconnect(fileSystemP, 0, panel, 0); fileSystemP->deleteLater(); fileSystemP = fileSystem; // v != 0 so this is safe } else { if (fileSystemP->isRefreshing()) { delayTimer.start(100); /* if filesystem is busy try refreshing later */ return; } } // (re)connect filesystem signals disconnect(files(), 0, panel, 0); connect(files(), &DirListerInterface::scanDone, panel, &ListPanel::slotStartUpdate); connect(files(), &FileSystem::fileSystemInfoChanged, panel, &ListPanel::updateFilesystemStats); connect(files(), &FileSystem::refreshJobStarted, panel, &ListPanel::slotRefreshJobStarted); connect(files(), SIGNAL(error(QString)), panel, SLOT(slotFilesystemError(QString))); panel->view->setFiles(files()); if(!history->currentItem().isEmpty() && isEqualUrl) { // if the url we're refreshing into is the current one, then the // partial refresh will not generate the needed signals to actually allow the // view to use nameToMakeCurrent. do it here instead (patch by Thomas Jarosch) panel->view->setCurrentItem(history->currentItem()); panel->view->makeItemVisible(panel->view->getCurrentKrViewItem()); } panel->view->setNameToMakeCurrent(history->currentItem()); // workaround for detecting panel deletion while filesystem is refreshing QPointer panelSave = panel; // NOTE: this is blocking. Returns false on error or interruption (cancel requested or panel // was deleted) const bool scanned = fileSystemP->refresh(url); if (scanned) { // update the history and address bar, as the actual url might differ from the one requested history->setCurrentUrl(fileSystemP->currentDirectory()); panel->setNavigatorUrl(fileSystemP->currentDirectory()); } else if (!panelSave) { return; } panel->view->setNameToMakeCurrent(QString()); panel->setCursor(Qt::ArrowCursor); // on local file system change the working directory if (files()->isLocal()) QDir::setCurrent(KrServices::urlToLocalPath(files()->currentDirectory())); // see if the open url operation failed, and if so, // put the attempted url in the navigator bar and let the user change it if (!scanned) { if(isSyncing(url)) panel->otherPanel()->gui->syncBrowseButton->setChecked(false); else if(urlManuallyEntered) { panel->setNavigatorUrl(url); if(panel == ACTIVE_PANEL) panel->editLocation(); } } if(otherFunc()->otherFunc() == this) // not true if our tab is not active otherFunc()->syncURL = QUrl(); urlManuallyEntered = false; refreshActions(); } void ListPanelFunc::setPaused(bool paused) { if (paused == _isPaused) return; _isPaused = paused; // TODO: disable refresh() in local file system when paused if (!_isPaused && _refreshAfterPaused) refresh(); } void ListPanelFunc::redirectLink() { if (!files()->isLocal()) { KMessageBox::sorry(krMainWindow, i18n("You can edit links only on local file systems")); return ; } FileItem *fileitem = files()->getFileItem(panel->getCurrentName()); if (!fileitem) return ; QString file = fileitem->getUrl().path(); QString currentLink = fileitem->getSymDest(); if (currentLink.isEmpty()) { KMessageBox::sorry(krMainWindow, i18n("The current file is not a link, so it cannot be redirected.")); return ; } // ask the user for a new destination bool ok = false; QString newLink = QInputDialog::getText(krMainWindow, i18n("Link Redirection"), i18n("Please enter the new link destination:"), QLineEdit::Normal, currentLink, &ok); // if the user canceled - quit if (!ok || newLink == currentLink) return ; // delete the current link if (unlink(file.toLocal8Bit()) == -1) { KMessageBox::sorry(krMainWindow, i18n("Cannot remove old link: %1", file)); return ; } // try to create a new symlink if (symlink(newLink.toLocal8Bit(), file.toLocal8Bit()) == -1) { KMessageBox:: /* --=={ Patch by Heiner }==-- */sorry(krMainWindow, i18n("Failed to create a new link: %1", file)); return ; } } void ListPanelFunc::krlink(bool sym) { if (!files()->isLocal()) { KMessageBox::sorry(krMainWindow, i18n("You can create links only on local file systems")); return; } QString name = panel->getCurrentName(); // ask the new link name.. bool ok = false; QString linkName = QInputDialog::getText(krMainWindow, i18n("New Link"), i18n("Create a new link to: %1", name), QLineEdit::Normal, name, &ok); // if the user canceled - quit if (!ok || linkName == name) return; // if the name is already taken - quit if (files()->getFileItem(linkName) != 0) { KMessageBox::sorry(krMainWindow, i18n("A folder or a file with this name already exists.")); return; } // make link name and target absolute path if (linkName.left(1) != "/") linkName = files()->currentDirectory().path() + '/' + linkName; name = files()->getUrl(name).path(); if (sym) { if (symlink(name.toLocal8Bit(), linkName.toLocal8Bit()) == -1) KMessageBox::sorry(krMainWindow, i18n("Failed to create a new symlink '%1' to: '%2'", linkName, name)); } else { if (link(name.toLocal8Bit(), linkName.toLocal8Bit()) == -1) KMessageBox::sorry(krMainWindow, i18n("Failed to create a new link '%1' to '%2'", linkName, name)); } } void ListPanelFunc::view() { QString fileName = panel->getCurrentName(); if (fileName.isNull()) return ; // if we're trying to view a directory, just exit FileItem *fileitem = files()->getFileItem(fileName); if (!fileitem || fileitem->isDir()) return ; if (!fileitem->isReadable()) { KMessageBox::sorry(0, i18n("No permissions to view this file.")); return ; } // call KViewer. KrViewer::view(files()->getUrl(fileName)); // nothing more to it! } void ListPanelFunc::viewDlg() { // ask the user for a url to view QUrl dest = KChooseDir::getFile(i18n("Enter a URL to view:"), panel->virtualPath(), panel->virtualPath()); if (dest.isEmpty()) return ; // the user canceled KrViewer::view(dest); // view the file } void ListPanelFunc::terminal() { SLOTS->runTerminal(panel->lastLocalPath()); } void ListPanelFunc::edit() { KFileItem tmp; if (fileToCreate.isEmpty()) { QString name = panel->getCurrentName(); if (name.isNull()) return; fileToCreate = files()->getUrl(name); } tmp = KFileItem(fileToCreate); if (tmp.isDir()) { KMessageBox::sorry(krMainWindow, i18n("You cannot edit a folder")); fileToCreate = QUrl(); return ; } if (!tmp.isReadable()) { KMessageBox::sorry(0, i18n("No permissions to edit this file.")); fileToCreate = QUrl(); return; } KrViewer::edit(fileToCreate); fileToCreate = QUrl(); } void ListPanelFunc::editNew() { if(!fileToCreate.isEmpty()) return; // ask the user for the filename to edit fileToCreate = KChooseDir::getFile(i18n("Enter the filename to edit:"), panel->virtualPath(), panel->virtualPath()); if(fileToCreate.isEmpty()) return ; // the user canceled // if the file exists, edit it instead of creating a new one QFile f(fileToCreate.toLocalFile()); if(f.exists()) { edit(); } else { QTemporaryFile *tempFile = new QTemporaryFile; tempFile->open(); KIO::CopyJob *job = KIO::copy(QUrl::fromLocalFile(tempFile->fileName()), fileToCreate); job->setUiDelegate(0); job->setDefaultPermissions(true); connect(job, SIGNAL(result(KJob*)), SLOT(slotFileCreated(KJob*))); connect(job, SIGNAL(result(KJob*)), tempFile, SLOT(deleteLater())); } } void ListPanelFunc::slotFileCreated(KJob *job) { if(!job->error() || job->error() == KIO::ERR_FILE_ALREADY_EXIST) { KrViewer::edit(fileToCreate); if(KIO::upUrl(fileToCreate).matches(panel->virtualPath(), QUrl::StripTrailingSlash)) refresh(); else if(KIO::upUrl(fileToCreate).matches(panel->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)) otherFunc()->refresh(); } else KMessageBox::sorry(krMainWindow, job->errorString()); fileToCreate = QUrl(); } void ListPanelFunc::copyFiles(bool enqueue, bool move) { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety QUrl destination = panel->otherPanel()->virtualPath(); bool fullDestPath = false; if (fileNames.count() == 1 && otherFunc()->files()->type() != FileSystem::FS_VIRTUAL) { FileItem *item = files()->getFileItem(fileNames[0]); if (item && !item->isDir()) { fullDestPath = true; // add original filename to destination destination.setPath(QDir(destination.path()).filePath(item->getUrl().fileName())); } } if (!fullDestPath) { destination = FileSystem::ensureTrailingSlash(destination); } const KConfigGroup group(krConfig, "Advanced"); const bool showDialog = move ? group.readEntry("Confirm Move", _ConfirmMove) : group.readEntry("Confirm Copy", _ConfirmCopy); if (showDialog) { QString operationText; if (move) { operationText = fileNames.count() == 1 ? i18n("Move %1 to:", fileNames.first()) : i18np("Move %1 file to:", "Move %1 files to:", fileNames.count()); } else { operationText = fileNames.count() == 1 ? i18n("Copy %1 to:", fileNames.first()) : i18np("Copy %1 file to:", "Copy %1 files to:", fileNames.count()); } // ask the user for the copy/move dest const KChooseDir::ChooseResult result = KChooseDir::getCopyDir(operationText, destination, panel->virtualPath()); destination = result.url; if (destination.isEmpty()) return ; // the user canceled enqueue = result.enqueue; } const JobMan::StartMode startMode = enqueue && krJobMan->isQueueModeEnabled() ? JobMan::Delay : !enqueue && !krJobMan->isQueueModeEnabled() ? JobMan::Start : JobMan::Enqueue; const QList fileUrls = files()->getUrls(fileNames); if (move) { // after the delete return the cursor to the first unmarked file above the current item panel->prepareToDelete(); } // make sure the user does not overwrite multiple files by mistake if (fileNames.count() > 1) { destination = FileSystem::ensureTrailingSlash(destination); } const KIO::CopyJob::CopyMode mode = move ? KIO::CopyJob::Move : KIO::CopyJob::Copy; FileSystemProvider::instance().startCopyFiles(fileUrls, destination, mode, true, startMode); if(KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { panel->view->saveSelection(); panel->view->unselectAll(); } } // called from SLOTS to begin the renaming process void ListPanelFunc::rename() { panel->view->renameCurrentItem(); } // called by signal itemRenamed() from the view to complete the renaming process void ListPanelFunc::rename(const QString &oldname, const QString &newname) { if (oldname == newname) return ; // do nothing // set current after rename panel->view->setNameToMakeCurrent(newname); // as always - the filesystem do the job files()->rename(oldname, newname); } void ListPanelFunc::mkdir() { // ask the new dir name.. // suggested name is the complete name for the directories // while filenames are suggested without their extension QString suggestedName = panel->getCurrentName(); if (!suggestedName.isEmpty() && !files()->getFileItem(suggestedName)->isDir()) suggestedName = QFileInfo(suggestedName).completeBaseName(); QString dirName = QInputDialog::getText(krMainWindow, i18n("New folder"), i18n("Folder's name:"), QLineEdit::Normal, suggestedName); // if the user canceled - quit if (dirName.isEmpty()) return ; QStringList dirTree = dirName.split('/'); for (QStringList::Iterator it = dirTree.begin(); it != dirTree.end(); ++it) { if (*it == ".") continue; if (*it == "..") { immediateOpenUrl(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); continue; } // check if the name is already taken if (files()->getFileItem(*it)) { // if it is the last dir to be created - quit if (*it == dirTree.last()) { KMessageBox::sorry(krMainWindow, i18n("A folder or a file with this name already exists.")); return ; } // else go into this dir else { immediateOpenUrl(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); continue; } } panel->view->setNameToMakeCurrent(*it); // as always - the filesystem does the job files()->mkDir(*it); if (dirTree.count() > 1) immediateOpenUrl(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); } // for } void ListPanelFunc::defaultDeleteFiles(bool invert) { const bool trash = KConfigGroup(krConfig, "General").readEntry("Move To Trash", _MoveToTrash); deleteFiles(trash != invert); } void ListPanelFunc::deleteFiles(bool moveToTrash) { if (files()->type() == FileSystem::FS_VIRTUAL && files()->isRoot()) { // only virtual deletion possible removeVirtualFiles(); return; } // first get the selected file names list QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return; // move to trash: only if possible moveToTrash = moveToTrash && files()->canMoveToTrash(fileNames); // now ask the user if he/she is sure: const KConfigGroup advancedGroup(krConfig, "Advanced"); if (advancedGroup.readEntry("Confirm Delete", _ConfirmDelete)) { QString s; // text KGuiItem b; // continue button if (moveToTrash) { s = i18np("Do you really want to move this item to the trash?", "Do you really want to move these %1 items to the trash?", fileNames.count()); b = KGuiItem(i18n("&Trash")); } else if (files()->type() == FileSystem::FS_VIRTUAL) { s = i18np("Do you really want to delete this item physically (not just " "removing it from the virtual items)?", "Do you really want to delete these %1 items physically (not just " "removing them from the virtual items)?", fileNames.count()); b = KStandardGuiItem::del(); } else { s = i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", fileNames.count()); b = KStandardGuiItem::del(); } // show message // note: i'm using continue and not yes/no because the yes/no has cancel as default button if (KMessageBox::warningContinueCancelList(krMainWindow, s, fileNames, i18n("Warning"), b) != KMessageBox::Continue) return; } // we want to warn the user about non empty dir bool emptyDirVerify = advancedGroup.readEntry("Confirm Unempty Dir", _ConfirmUnemptyDir); // TODO only local fs supported emptyDirVerify &= files()->isLocal(); if (emptyDirVerify) { QMutableStringListIterator it(fileNames); while (it.hasNext()) { const QString fileName = it.next(); FileItem *fileItem = files()->getFileItem(fileName); if (fileItem && !fileItem->isSymLink() && fileItem->isDir()) { // read local dir... const QDir dir(fileItem->getUrl().toLocalFile()); if (!dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot).isEmpty()) { // ...is not empty, ask user const KMessageBox::ButtonCode result = KMessageBox::warningYesNoCancel( krMainWindow, i18n("

Folder %1 is not empty.

", fileName) + (moveToTrash ? i18n("

Skip this one or trash all?

") : i18n("

Skip this one or delete all?

")), QString(), KGuiItem(i18n("&Skip")), KGuiItem(moveToTrash ? i18n("&Trash All") : i18n("&Delete All"))); if (result == KMessageBox::Yes) { it.remove(); // skip } else if (result == KMessageBox::No) { break; // accept all remaining } else { return; // cancel } } } } if (fileNames.isEmpty()) return; // nothing to delete } // after the delete return the cursor to the first unmarked // file above the current item; panel->prepareToDelete(); // let the filesystem do the job... files()->deleteFiles(fileNames, moveToTrash); } void ListPanelFunc::removeVirtualFiles() { if (files()->type() != FileSystem::FS_VIRTUAL) { krOut << "filesystem not virtual"; return; } const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return; const QString text = i18np("Do you really want to delete this virtual item (physical files stay untouched)?", "Do you really want to delete these %1 virtual items (physical files stay " "untouched)?", fileNames.count()); if (KMessageBox::warningContinueCancelList(krMainWindow, text, fileNames, i18n("Warning"), KStandardGuiItem::remove()) != KMessageBox::Continue) return; VirtualFileSystem *fileSystem = static_cast(files()); fileSystem->remove(fileNames); } void ListPanelFunc::goInside(const QString& name) { openFileNameInternal(name, false); } void ListPanelFunc::runCommand(QString cmd) { krOut << "Run command: " << cmd; const QString workdir = panel->virtualPath().isLocalFile() ? panel->virtualPath().path() : QDir::homePath(); if(!KRun::runCommand(cmd, krMainWindow, workdir)) KMessageBox::error(0, i18n("Could not start %1", cmd)); } void ListPanelFunc::runService(const KService &service, QList urls) { krOut << "Run service: " << service.name(); KIO::DesktopExecParser parser(service, urls); QStringList args = parser.resultingArguments(); if (!args.isEmpty()) runCommand(KShell::joinArgs(args)); else KMessageBox::error(0, i18n("%1 cannot open %2", service.name(), KrServices::toStringList(urls).join(", "))); } void ListPanelFunc::displayOpenWithDialog(QList urls) { // NOTE: we are not using KRun::displayOpenWithDialog() because we want the commands working // directory to be the panel directory KOpenWithDialog dialog(urls, panel); dialog.hideRunInTerminal(); if (dialog.exec()) { KService::Ptr service = dialog.service(); if(!service) service = KService::Ptr(new KService(dialog.text(), dialog.text(), QString())); runService(*service, urls); } } QUrl ListPanelFunc::browsableArchivePath(const QString &filename) { FileItem *fileitem = files()->getFileItem(filename); QUrl url = files()->getUrl(filename); QString mime = fileitem->getMime(); if(url.isLocalFile()) { QString protocol = KrServices::registeredProtocol(mime); if(!protocol.isEmpty()) { url.setScheme(protocol); return url; } } return QUrl(); } // this is done when you double click on a file void ListPanelFunc::execute(const QString& name) { openFileNameInternal(name, true); } void ListPanelFunc::pack() { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety if (fileNames.count() == 0) return ; // nothing to pack // choose the default name QString defaultName = panel->virtualPath().fileName(); if (defaultName.isEmpty()) defaultName = "pack"; if (fileNames.count() == 1) defaultName = fileNames.first(); // ask the user for archive name and packer new PackGUI(defaultName, panel->otherPanel()->virtualPath().toDisplayString(QUrl::PreferLocalFile | QUrl::StripTrailingSlash), fileNames.count(), fileNames.first()); if (PackGUI::type.isEmpty()) { return ; // the user canceled } // check for partial URLs if (!PackGUI::destination.contains(":/") && !PackGUI::destination.startsWith('/')) { PackGUI::destination = panel->virtualPath().toDisplayString() + '/' + PackGUI::destination; } QString destDir = PackGUI::destination; if (!destDir.endsWith('/')) destDir += '/'; bool packToOtherPanel = (destDir == FileSystem::ensureTrailingSlash(panel->otherPanel()->virtualPath()).toDisplayString(QUrl::PreferLocalFile)); QUrl destURL = QUrl::fromUserInput(destDir + PackGUI::filename + '.' + PackGUI::type, QString(), QUrl::AssumeLocalFile); if (destURL.isLocalFile() && QFile::exists(destURL.path())) { QString msg = i18n("

The archive %1.%2 already exists. Do you want to overwrite it?

All data in the previous archive will be lost.

", PackGUI::filename, PackGUI::type); if (PackGUI::type == "zip") { msg = i18n("

The archive %1.%2 already exists. Do you want to overwrite it?

Zip will replace identically named entries in the zip archive or add entries for new names.

", PackGUI::filename, PackGUI::type); } if (KMessageBox::warningContinueCancel(krMainWindow, msg, QString(), KStandardGuiItem::overwrite()) == KMessageBox::Cancel) return ; // stop operation } else if (destURL.scheme() == QStringLiteral("virt")) { KMessageBox::error(krMainWindow, i18n("Cannot pack files onto a virtual destination.")); return; } PackJob * job = PackJob::createPacker(files()->currentDirectory(), destURL, fileNames, PackGUI::type, PackGUI::extraProps); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); if (packToOtherPanel) connect(job, SIGNAL(result(KJob*)), panel->otherPanel()->func, SLOT(refresh())); } void ListPanelFunc::testArchive() { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety TestArchiveJob * job = TestArchiveJob::testArchives(files()->currentDirectory(), fileNames); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); } void ListPanelFunc::unpack() { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety QString s; if (fileNames.count() == 1) s = i18n("Unpack %1 to:", fileNames[0]); else s = i18np("Unpack %1 file to:", "Unpack %1 files to:", fileNames.count()); // ask the user for the copy dest QUrl dest = KChooseDir::getDir(s, panel->otherPanel()->virtualPath(), panel->virtualPath()); if (dest.isEmpty()) return ; // the user canceled bool packToOtherPanel = (dest.matches(panel->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)); UnpackJob * job = UnpackJob::createUnpacker(files()->currentDirectory(), dest, fileNames); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); if (packToOtherPanel) connect(job, SIGNAL(result(KJob*)), panel->otherPanel()->func, SLOT(refresh())); } void ListPanelFunc::createChecksum() { if (!panel->func->files()->isLocal()) return; // only local, non-virtual files are supported KrViewItemList items; panel->view->getSelectedKrViewItems(&items); QStringList fileNames; for (KrViewItem *item : items) { FileItem *file = panel->func->getFileItem(item); fileNames.append(file->getUrl().fileName()); } if (fileNames.isEmpty()) return; // nothing selected and no valid current file Checksum::startCreationWizard(panel->virtualPath().toLocalFile(), fileNames); } void ListPanelFunc::matchChecksum() { if (!panel->func->files()->isLocal()) return; // only local, non-virtual files are supported FileItem *currentItem = files()->getFileItem(panel->getCurrentName()); const QString checksumFilePath = currentItem ? currentItem->getUrl().toLocalFile() : QString(); Checksum::startVerifyWizard(panel->virtualPath().toLocalFile(), checksumFilePath); } void ListPanelFunc::calcSpace() { QStringList fileNames; panel->view->getSelectedItems(&fileNames); if (fileNames.isEmpty()) { // current file is ".." dummy file panel->view->selectAllIncludingDirs(); panel->view->getSelectedItems(&fileNames); } SizeCalculator *sizeCalculator = createAndConnectSizeCalculator(files()->getUrls(fileNames)); KrCalcSpaceDialog::showDialog(panel, sizeCalculator); } void ListPanelFunc::quickCalcSpace() { const QString currentName = panel->getCurrentName(); if (currentName.isEmpty()) { // current file is ".." dummy, do a verbose calcSpace calcSpace(); return; } if (!_quickSizeCalculator) { _quickSizeCalculator = createAndConnectSizeCalculator(QList()); panel->connectQuickSizeCalculator(_quickSizeCalculator); } _quickSizeCalculator->add(files()->getUrl(currentName)); } SizeCalculator *ListPanelFunc::createAndConnectSizeCalculator(const QList &urls) { SizeCalculator *sizeCalculator = new SizeCalculator(urls); connect(sizeCalculator, &SizeCalculator::calculated, this, &ListPanelFunc::slotSizeCalculated); connect(sizeCalculator, &SizeCalculator::finished, panel, &ListPanel::slotUpdateTotals); connect(this, &ListPanelFunc::destroyed, sizeCalculator, &SizeCalculator::deleteLater); return sizeCalculator; } void ListPanelFunc::slotSizeCalculated(const QUrl &url, KIO::filesize_t size) { KrViewItem *item = panel->view->findItemByUrl(url); if (!item) return; item->setSize(size); item->redraw(); } void ListPanelFunc::FTPDisconnect() { // you can disconnect only if connected! if (files()->isRemote()) { panel->_actions->actFTPDisconnect->setEnabled(false); panel->view->setNameToMakeCurrent(QString()); openUrl(QUrl::fromLocalFile(panel->lastLocalPath())); } } void ListPanelFunc::newFTPconnection() { QUrl url = KRSpWidgets::newFTP(); // if the user canceled - quit if (url.isEmpty()) return ; panel->_actions->actFTPDisconnect->setEnabled(true); openUrl(url); } void ListPanelFunc::properties() { const QStringList names = panel->getSelectedNames(); if (names.isEmpty()) return ; // no names... KFileItemList fi; for (int i = 0 ; i < names.count() ; ++i) { FileItem *fileitem = files()->getFileItem(names[i]); if (!fileitem) continue; QUrl url = files()->getUrl(names[i]); fi.push_back(KFileItem(fileitem->getEntry(), url)); } if (fi.isEmpty()) return ; // Show the properties dialog KPropertiesDialog *dlg = new KPropertiesDialog(fi, krMainWindow); connect(dlg, SIGNAL(applied()), SLOT(refresh())); dlg->show(); } void ListPanelFunc::refreshActions() { panel->updateButtons(); if(ACTIVE_PANEL != panel) return; QString protocol = files()->currentDirectory().scheme(); krRemoteEncoding->setEnabled(protocol == "ftp" || protocol == "sftp" || protocol == "fish" || protocol == "krarc"); //krMultiRename->setEnabled( fileSystemType == FileSystem::FS_NORMAL ); // batch rename //krProperties ->setEnabled( fileSystemType == FileSystem::FS_NORMAL || fileSystemType == FileSystem::FS_FTP ); // file properties /* krUnpack->setEnabled(true); // unpack archive krTest->setEnabled(true); // test archive krSelect->setEnabled(true); // select a group by filter krSelectAll->setEnabled(true); // select all files krUnselect->setEnabled(true); // unselect by filter krUnselectAll->setEnabled( true); // remove all selections krInvert->setEnabled(true); // invert the selection krFTPConnect->setEnabled(true); // connect to an ftp krFTPNew->setEnabled(true); // create a new connection krAllFiles->setEnabled(true); // show all files in list krCustomFiles->setEnabled(true); // show a custom set of files krRoot->setEnabled(true); // go all the way up krExecFiles->setEnabled(true); // show only executables */ panel->_actions->setViewActions[panel->panelType]->setChecked(true); panel->_actions->actFTPDisconnect->setEnabled(files()->isRemote()); // allow disconnecting a network session panel->_actions->actCreateChecksum->setEnabled(files()->isLocal()); panel->_actions->actDirUp->setEnabled(!files()->isRoot()); panel->_actions->actRoot->setEnabled(!panel->virtualPath().matches(QUrl::fromLocalFile(ROOT_DIR), QUrl::StripTrailingSlash)); panel->_actions->actHome->setEnabled(!atHome()); panel->_actions->actHistoryBackward->setEnabled(history->canGoBack()); panel->_actions->actHistoryForward->setEnabled(history->canGoForward()); panel->view->op()->emitRefreshActions(); } FileSystem* ListPanelFunc::files() { if (!fileSystemP) fileSystemP = FileSystemProvider::instance().getFilesystem(QUrl::fromLocalFile(ROOT_DIR)); return fileSystemP; } QUrl ListPanelFunc::virtualDirectory() { return _isPaused ? history->currentUrl() : files()->currentDirectory(); } FileItem *ListPanelFunc::getFileItem(const QString &name) { return files()->getFileItem(name); } FileItem *ListPanelFunc::getFileItem(KrViewItem *item) { return files()->getFileItem(item->name()); } void ListPanelFunc::clipboardChanged(QClipboard::Mode mode) { if (mode == QClipboard::Clipboard && this == copyToClipboardOrigin) { disconnect(QApplication::clipboard(), 0, this, 0); copyToClipboardOrigin = 0; } } void ListPanelFunc::copyToClipboard(bool move) { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety QList fileUrls = files()->getUrls(fileNames); QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-kde-cutselection", move ? "1" : "0"); mimeData->setUrls(fileUrls); if (copyToClipboardOrigin) disconnect(QApplication::clipboard(), 0, copyToClipboardOrigin, 0); copyToClipboardOrigin = this; QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); connect(QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), this, SLOT(clipboardChanged(QClipboard::Mode))); } void ListPanelFunc::pasteFromClipboard() { QClipboard * cb = QApplication::clipboard(); ListPanelFunc *origin = 0; if (copyToClipboardOrigin) { disconnect(QApplication::clipboard(), 0, copyToClipboardOrigin, 0); origin = copyToClipboardOrigin; copyToClipboardOrigin = 0; } bool move = false; const QMimeData *data = cb->mimeData(); if (data->hasFormat("application/x-kde-cutselection")) { QByteArray a = data->data("application/x-kde-cutselection"); if (!a.isEmpty()) move = (a.at(0) == '1'); // true if 1 } QList urls = data->urls(); if (urls.isEmpty()) return ; if(origin && KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { origin->panel->view->saveSelection(); for(KrViewItem *item = origin->panel->view->getFirst(); item != 0; item = origin->panel->view->getNext(item)) { if (urls.contains(item->getFileItem()->getUrl())) item->setSelected(false); } } files()->addFiles(urls, move ? KIO::CopyJob::Move : KIO::CopyJob::Copy); } ListPanelFunc* ListPanelFunc::otherFunc() { return panel->otherPanel()->func; } void ListPanelFunc::historyGotoPos(int pos) { if(history->gotoPos(pos)) refresh(); } void ListPanelFunc::historyBackward() { if(history->goBack()) refresh(); } void ListPanelFunc::historyForward() { if(history->goForward()) refresh(); } void ListPanelFunc::dirUp() { openUrl(KIO::upUrl(files()->currentDirectory()), files()->currentDirectory().fileName()); } void ListPanelFunc::home() { openUrl(QUrl::fromLocalFile(QDir::homePath())); } void ListPanelFunc::root() { openUrl(QUrl::fromLocalFile(ROOT_DIR)); } void ListPanelFunc::cdToOtherPanel() { openUrl(panel->otherPanel()->virtualPath()); } void ListPanelFunc::syncOtherPanel() { otherFunc()->openUrl(panel->virtualPath()); } bool ListPanelFunc::atHome() { return QUrl::fromLocalFile(QDir::homePath()).matches(panel->virtualPath(), QUrl::StripTrailingSlash); } diff --git a/krusader/Panel/panelpopup.cpp b/krusader/Panel/panelpopup.cpp index c813ab56..ad05e42a 100644 --- a/krusader/Panel/panelpopup.cpp +++ b/krusader/Panel/panelpopup.cpp @@ -1,303 +1,303 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "panelpopup.h" #include "krfiletreeview.h" #include "krpanel.h" -#include "krview.h" -#include "krviewitem.h" #include "panelfunc.h" #include "viewactions.h" #include "../defaults.h" #include "../kicons.h" #include "../Dialogs/krsqueezedtextlabel.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/filesystem.h" #include "../KViewer/diskusageviewer.h" #include "../KViewer/panelviewer.h" +#include "PanelView/krview.h" +#include "PanelView/krviewitem.h" // QtCore #include #include // QtWidgets #include #include #include #include #include PanelPopup::PanelPopup(QWidget *parent) : QWidget(parent), stack(0), imageFilePreview(0), pjob(0) { QGridLayout * layout = new QGridLayout(this); layout->setContentsMargins(0, 0, 0, 0); // create the label+buttons setup dataLine = new KrSqueezedTextLabel(this); KConfigGroup lg(krConfig, "Look&Feel"); dataLine->setFont(lg.readEntry("Filelist Font", _FilelistFont)); // --- hack: setup colors to be the same as an inactive panel dataLine->setBackgroundRole(QPalette::Window); int sheight = QFontMetrics(dataLine->font()).height() + 4; dataLine->setMaximumHeight(sheight); btns = new QButtonGroup(this); btns->setExclusive(true); connect(btns, SIGNAL(buttonClicked(int)), this, SLOT(tabSelected(int))); treeBtn = new QToolButton(this); treeBtn->setToolTip(i18n("Tree Panel: a tree view of the local file system")); treeBtn->setIcon(krLoader->loadIcon("view-list-tree", KIconLoader::Toolbar, 16)); treeBtn->setFixedSize(20, 20); treeBtn->setCheckable(true); btns->addButton(treeBtn, Tree); previewBtn = new QToolButton(this); previewBtn->setToolTip(i18n("Preview Panel: display a preview of the current file")); previewBtn->setIcon(krLoader->loadIcon("view-preview", KIconLoader::Toolbar, 16)); previewBtn->setFixedSize(20, 20); previewBtn->setCheckable(true); btns->addButton(previewBtn, Preview); viewerBtn = new QToolButton(this); viewerBtn->setToolTip(i18n("View Panel: view the current file")); viewerBtn->setIcon(krLoader->loadIcon("zoom-original", KIconLoader::Toolbar, 16)); viewerBtn->setFixedSize(20, 20); viewerBtn->setCheckable(true); btns->addButton(viewerBtn, View); duBtn = new QToolButton(this); duBtn->setToolTip(i18n("Disk Usage Panel: view the usage of a folder")); duBtn->setIcon(krLoader->loadIcon("kr_diskusage", KIconLoader::Toolbar, 16)); duBtn->setFixedSize(20, 20); duBtn->setCheckable(true); btns->addButton(duBtn, DskUsage); layout->addWidget(dataLine, 0, 0); layout->addWidget(treeBtn, 0, 1); layout->addWidget(previewBtn, 0, 2); layout->addWidget(viewerBtn, 0, 3); layout->addWidget(duBtn, 0, 4); // create a widget stack on which to put the parts stack = new QStackedWidget(this); // create the tree part ---------- tree = new KrFileTreeView(stack); tree->setAcceptDrops(true); tree->setDragDropMode(QTreeView::DropOnly); tree->setDropIndicatorShown(true); tree->setBriefMode(true); tree->setProperty("KrusaderWidgetId", QVariant(Tree)); stack->addWidget(tree); tree->setDirOnlyMode(true); // NOTE: the F2 key press event is caught before it gets to the tree tree->setEditTriggers(QAbstractItemView::EditKeyPressed); connect(tree, &KrFileTreeView::doubleClicked, this, &PanelPopup::treeSelection); connect(tree, &KrFileTreeView::activated, this, &PanelPopup::treeSelection); // create the quickview part ------ imageFilePreview = new KImageFilePreview(stack); imageFilePreview->setProperty("KrusaderWidgetId", QVariant(Preview)); stack->addWidget(imageFilePreview); // create the panelview fileViewer = new PanelViewer(stack); fileViewer->setProperty("KrusaderWidgetId", QVariant(View)); // kparts demand too much width QSizePolicy sizePolicy = fileViewer->sizePolicy(); sizePolicy.setHorizontalPolicy(QSizePolicy::Ignored); fileViewer->setSizePolicy(sizePolicy); stack->addWidget(fileViewer); connect(fileViewer, &PanelViewer::openUrlRequest, this, &PanelPopup::handleOpenUrlRequest); // create the disk usage view diskusage = new DiskUsageViewer(stack); diskusage->setStatusLabel(dataLine, i18n("Disk Usage:")); diskusage->setProperty("KrusaderWidgetId", QVariant(DskUsage)); stack->addWidget(diskusage); connect(diskusage, &DiskUsageViewer::openUrlRequest, this, &PanelPopup::handleOpenUrlRequest); // -------- finish the layout (General one) layout->addWidget(stack, 1, 0, 1, 5); hide(); // for not to open the 3rd hand tool at start (selecting the last used tab) setCurrentPage(0); } PanelPopup::~PanelPopup() {} void PanelPopup::saveSettings(KConfigGroup cfg) const { if (currentPage() == Tree) { cfg.writeEntry("TreeBriefMode", tree->briefMode()); } } void PanelPopup::restoreSettings(KConfigGroup cfg) { tree->setBriefMode(cfg.readEntry("TreeBriefMode", true)); } void PanelPopup::setCurrentPage(int id) { QAbstractButton * curr = btns->button(id); if (curr) { curr->click(); } } void PanelPopup::show() { QWidget::show(); tabSelected(currentPage()); } void PanelPopup::hide() { QWidget::hide(); if (currentPage() == View) fileViewer->closeUrl(); if (currentPage() == DskUsage) diskusage->closeUrl(); } void PanelPopup::focusInEvent(QFocusEvent*) { switch (currentPage()) { case Preview: if (!isHidden()) imageFilePreview->setFocus(); break; case View: if (!isHidden() && fileViewer->part() && fileViewer->part()->widget()) fileViewer->part()->widget()->setFocus(); break; case DskUsage: if (!isHidden() && diskusage->getWidget() && diskusage->getWidget()->currentWidget()) diskusage->getWidget()->currentWidget()->setFocus(); break; case Tree: if (!isHidden()) tree->setFocus(); break; } } void PanelPopup::handleOpenUrlRequest(const QUrl &url) { QMimeDatabase db; QMimeType mime = db.mimeTypeForUrl(url); if (mime.isValid() && mime.name() == "inode/directory") ACTIVE_PANEL->func->openUrl(url); } void PanelPopup::tabSelected(int id) { QUrl url; const FileItem *fileitem = 0; if (ACTIVE_PANEL && ACTIVE_PANEL->view) fileitem = ACTIVE_PANEL->func->files()->getFileItem(ACTIVE_PANEL->view->getCurrentItem()); if(fileitem) url = fileitem->getUrl(); // if tab is tree, set something logical in the data line switch (id) { case Tree: stack->setCurrentWidget(tree); dataLine->setText(i18n("Tree:")); if (!isHidden()) tree->setFocus(); if (ACTIVE_PANEL) tree->setCurrentUrl(ACTIVE_PANEL->virtualPath()); break; case Preview: stack->setCurrentWidget(imageFilePreview); dataLine->setText(i18n("Preview:")); update(fileitem); break; case View: stack->setCurrentWidget(fileViewer); dataLine->setText(i18n("View:")); update(fileitem); if (!isHidden() && fileViewer->part() && fileViewer->part()->widget()) fileViewer->part()->widget()->setFocus(); break; case DskUsage: stack->setCurrentWidget(diskusage); dataLine->setText(i18n("Disk Usage:")); update(fileitem); if (!isHidden() && diskusage->getWidget() && diskusage->getWidget()->currentWidget()) diskusage->getWidget()->currentWidget()->setFocus(); break; } if (id != View) fileViewer->closeUrl(); } // decide which part to update, if at all void PanelPopup::update(const FileItem *fileitem) { if (isHidden()) return; QUrl url; if(fileitem) url = fileitem->getUrl(); switch (currentPage()) { case Preview: imageFilePreview->showPreview(url); dataLine->setText(i18n("Preview: %1", url.fileName())); break; case View: if(fileitem && !fileitem->isDir() && fileitem->isReadable()) fileViewer->openUrl(fileitem->getUrl()); else fileViewer->closeUrl(); dataLine->setText(i18n("View: %1", url.fileName())); break; case DskUsage: { if(fileitem && !fileitem->isDir()) url = KIO::upUrl(url); dataLine->setText(i18n("Disk Usage: %1", url.fileName())); diskusage->openUrl(url); } break; case Tree: // nothing to do break; } } void PanelPopup::onPanelPathChange(const QUrl &url) { switch (currentPage()) { case Tree: if (url.isLocalFile()) { tree->setCurrentUrl(url); // synchronize panel path with tree path } break; } } // ------------------- tree void PanelPopup::treeSelection() { emit selection(tree->currentUrl()); //emit hideMe(); } diff --git a/krusader/Panel/viewactions.cpp b/krusader/Panel/viewactions.cpp index d4aa0a6e..9fc9d8aa 100644 --- a/krusader/Panel/viewactions.cpp +++ b/krusader/Panel/viewactions.cpp @@ -1,193 +1,193 @@ /*************************************************************************** viewactions.cpp ------------------- copyright : (C) 2010 by Jan Lepper e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "viewactions.h" -#include "krview.h" +#include "PanelView/krview.h" #include "../krmainwindow.h" #include #include ViewActions::ViewActions(QObject *parent, KrMainWindow *mainWindow) : ActionsBase(parent, mainWindow) { // zoom actZoomIn = action(i18n("Zoom In"), "zoom-in", 0, SLOT(zoomIn()), "zoom_in"); actZoomOut = action(i18n("Zoom Out"), "zoom-out", 0, SLOT(zoomOut()), "zoom_out"); actDefaultZoom = action(i18n("Default Zoom"), "zoom-original", 0, SLOT(defaultZoom()), "default_zoom"); // filter action(i18n("&All Files"), 0, Qt::SHIFT + Qt::Key_F10, SLOT(allFilter()), "all files"); //actExecFilter = new QAction( i18n( "&Executables" ), SHIFT + Qt::Key_F11, // SLOTS, SLOT(execFilter()), actionCollection(), "exec files" ); action(i18n("&Custom"), 0, Qt::SHIFT + Qt::Key_F12, SLOT(customFilter()), "custom files"); // selection actSelect = action(i18n("Select &Group..."), "edit-select", Qt::CTRL + Qt::Key_Plus, SLOT(markGroup()), "select group"); actSelectAll = action(i18n("&Select All"), "edit-select-all", Qt::ALT + Qt::Key_Plus, SLOT(markAll()), "select all"); actUnselect = action(i18n("&Unselect Group..."), "kr_unselect", Qt::CTRL + Qt::Key_Minus, SLOT(unmarkGroup()), "unselect group"); actUnselectAll = action(i18n("U&nselect All"), "edit-select-none", Qt::ALT + Qt::Key_Minus, SLOT(unmarkAll()), "unselect all"); actInvert = action(i18n("&Invert Selection"), "edit-select-invert", Qt::ALT + Qt::Key_Asterisk, SLOT(invertSelection()), "invert"); actRestoreSelection = action(i18n("Restore Selection"), 0, 0, SLOT(restoreSelection()), "restore_selection"); actMarkSameBaseName = action(i18n("Select Files with the Same Name"), 0, 0, SLOT(markSameBaseName()), "select_same_base_name"); actMarkSameExtension = action(i18n("Select Files with the Same Extension"), 0, 0, SLOT(markSameExtension()), "select_same_extension"); // other stuff action(i18n("Show View Options Menu"), 0, 0, SLOT(showOptionsMenu()), "show_view_options_menu"); action(i18n("Set Focus to the Panel"), 0, 0, SLOT(focusPanel()), "focus_panel"); action(i18n("Apply settings to other tabs"), 0, 0, SLOT(applySettingsToOthers()), "view_apply_settings_to_others"); actTogglePreviews = toggleAction(i18n("Show Previews"), 0, 0, SLOT(togglePreviews(bool)), "toggle previews"); QAction *actSaveaveDefaultSettings = action(i18n("Save settings as default"), 0, 0, SLOT(saveDefaultSettings()), "view_save_default_settings"); // tooltips actSelect->setToolTip(i18n("Select group")); actSelectAll->setToolTip(i18n("Select all files in the current folder")); actUnselectAll->setToolTip(i18n("Unselect all")); actSaveaveDefaultSettings->setToolTip(i18n("Save settings as default for new instances of this view type")); } inline KrView *ViewActions::view() { return _mainWindow->activeView(); } // zoom void ViewActions::zoomIn() { view()->zoomIn(); } void ViewActions::zoomOut() { view()->zoomOut(); } void ViewActions::defaultZoom() { view()->setDefaultFileIconSize(); } // filter void ViewActions::allFilter() { view()->setFilter(KrViewProperties::All); } #if 0 void ViewActions::execFilter() { view()->setFilter(KrViewProperties::All); } #endif void ViewActions::customFilter() { view()->setFilter(KrViewProperties::Custom); } void ViewActions::showOptionsMenu() { view()->showContextMenu(); } // selection void ViewActions::markAll() { view()->changeSelection(KRQuery("*"), true); } void ViewActions::unmarkAll() { view()->unselectAll(); } void ViewActions::markGroup() { view()->customSelection(true); } void ViewActions::unmarkGroup() { view()->customSelection(false); } void ViewActions::invertSelection() { view()->invertSelection(); } void ViewActions::restoreSelection() { view()->restoreSelection(); } void ViewActions::markSameBaseName() { view()->markSameBaseName(); } void ViewActions::markSameExtension() { view()->markSameExtension(); } // other stuff void ViewActions::saveDefaultSettings() { view()->saveDefaultSettings(); } void ViewActions::applySettingsToOthers() { view()->applySettingsToOthers(); } void ViewActions::focusPanel() { view()->widget()->setFocus(); } void ViewActions::togglePreviews(bool show) { view()->showPreviews(show); } void ViewActions::refreshActions() { actDefaultZoom->setEnabled(view()->defaultFileIconSize() != view()->fileIconSize()); int idx = KrView::iconSizes.indexOf(view()->fileIconSize()); actZoomOut->setEnabled(idx > 0); actZoomIn->setEnabled(idx < (KrView::iconSizes.count() - 1)); actRestoreSelection->setEnabled(view()->canRestoreSelection()); actTogglePreviews->setChecked(view()->previewsShown()); } diff --git a/krusader/Search/krsearchdialog.cpp b/krusader/Search/krsearchdialog.cpp index 13da65a4..57414c8e 100644 --- a/krusader/Search/krsearchdialog.cpp +++ b/krusader/Search/krsearchdialog.cpp @@ -1,678 +1,678 @@ /*************************************************************************** krsearchdialog.cpp ------------------- copyright : (C) 2001 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krsearchdialog.h" // QtCore #include #include // QtGui #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include "krsearchmod.h" #include "../Dialogs/krdialogs.h" #include "../Dialogs/krspecialwidgets.h" #include "../Dialogs/krsqueezedtextlabel.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/krquery.h" #include "../FileSystem/virtualfilesystem.h" #include "../Filter/filtertabs.h" #include "../Filter/generalfilter.h" #include "../KViewer/krviewer.h" +#include "../Panel/PanelView/krview.h" +#include "../Panel/PanelView/krviewfactory.h" +#include "../Panel/PanelView/krviewitem.h" #include "../Panel/krpanel.h" #include "../Panel/krsearchbar.h" -#include "../Panel/krview.h" -#include "../Panel/krviewfactory.h" -#include "../Panel/krviewitem.h" #include "../Panel/panelfunc.h" #include "../defaults.h" #include "../kicons.h" #include "../kractions.h" #include "../krglobal.h" #include "../krservices.h" #include "../krslots.h" #include "../krusaderview.h" #include "../panelmanager.h" #define RESULTVIEW_TYPE 0 class SearchResultContainer : public DirListerInterface { public: explicit SearchResultContainer(QObject *parent) : DirListerInterface(parent) {} virtual ~SearchResultContainer() { clear(); } virtual QList fileItems() const Q_DECL_OVERRIDE { return _fileItems; } virtual unsigned long numFileItems() const Q_DECL_OVERRIDE { return _fileItems.count(); } virtual bool isRoot() const Q_DECL_OVERRIDE { return true; } void clear() { emit cleared(); foreach(FileItem *fileitem, _fileItems) delete fileitem; _fileItems.clear(); _foundText.clear(); } void addItem(const FileItem &file, const QString &foundText) { const QString path = file.getUrl().toDisplayString(QUrl::PreferLocalFile); FileItem *fileitem = FileItem::createCopy(file, path); _fileItems << fileitem; if(!foundText.isEmpty()) _foundText[fileitem] = foundText; emit addedFileItem(fileitem); } QString foundText(const FileItem *fileitem) { return _foundText[fileitem]; } private: QList _fileItems; QHash _foundText; }; KrSearchDialog *KrSearchDialog::SearchDialog = 0; QString KrSearchDialog::lastSearchText = QString('*'); int KrSearchDialog::lastSearchType = 0; bool KrSearchDialog::lastSearchForCase = false; bool KrSearchDialog::lastContainsWholeWord = false; bool KrSearchDialog::lastContainsWithCase = false; bool KrSearchDialog::lastSearchInSubDirs = true; bool KrSearchDialog::lastSearchInArchives = false; bool KrSearchDialog::lastFollowSymLinks = false; bool KrSearchDialog::lastContainsRegExp = false; // class starts here ///////////////////////////////////////// KrSearchDialog::KrSearchDialog(QString profile, QWidget* parent) : QDialog(parent), query(0), searcher(0), isBusy(false), closed(false) { KConfigGroup group(krConfig, "Search"); setWindowTitle(i18n("Krusader::Search")); setWindowIcon(QIcon::fromTheme("system-search")); QGridLayout* searchBaseLayout = new QGridLayout(this); searchBaseLayout->setSpacing(6); searchBaseLayout->setContentsMargins(11, 11, 11, 11); // creating the dialog buttons ( Search, Stop, Close ) QHBoxLayout* buttonsLayout = new QHBoxLayout(); buttonsLayout->setSpacing(6); buttonsLayout->setContentsMargins(0, 0, 0, 0); profileManager = new ProfileManager("SearcherProfile", this); buttonsLayout->addWidget(profileManager); searchTextToClipboard = new QCheckBox(this); searchTextToClipboard->setText(i18n("Query to clipboard")); searchTextToClipboard->setToolTip(i18n("Place search text to clipboard when a found file is opened.")); searchTextToClipboard->setCheckState(static_cast(group.readEntry("QueryToClipboard", 0))); connect(searchTextToClipboard, &QCheckBox::stateChanged, this, [=](int state) { KConfigGroup group(krConfig, "Search"); group.writeEntry("QueryToClipboard", state); }); buttonsLayout->addWidget(searchTextToClipboard); QSpacerItem* spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); buttonsLayout->addItem(spacer); mainFeedToListBoxBtn = new QPushButton(this); mainFeedToListBoxBtn->setText(i18n("Feed to listbox")); mainFeedToListBoxBtn->setIcon(QIcon::fromTheme("list-add")); mainFeedToListBoxBtn->setEnabled(false); buttonsLayout->addWidget(mainFeedToListBoxBtn); mainSearchBtn = new QPushButton(this); mainSearchBtn->setText(i18n("Search")); mainSearchBtn->setIcon(QIcon::fromTheme("edit-find")); mainSearchBtn->setDefault(true); buttonsLayout->addWidget(mainSearchBtn); mainStopBtn = new QPushButton(this); mainStopBtn->setEnabled(false); mainStopBtn->setText(i18n("Stop")); mainStopBtn->setIcon(QIcon::fromTheme("process-stop")); buttonsLayout->addWidget(mainStopBtn); mainCloseBtn = new QPushButton(this); mainCloseBtn->setText(i18n("Close")); mainCloseBtn->setIcon(QIcon::fromTheme("dialog-close")); buttonsLayout->addWidget(mainCloseBtn); searchBaseLayout->addLayout(buttonsLayout, 1, 0); // creating the searcher tabs searcherTabs = new QTabWidget(this); filterTabs = FilterTabs::addTo(searcherTabs, FilterTabs::Default); generalFilter = (GeneralFilter *)filterTabs->get("GeneralFilter"); QWidget* resultTab = new QWidget(searcherTabs); QGridLayout* resultLayout = new QGridLayout(resultTab); resultLayout->setSpacing(6); resultLayout->setContentsMargins(6, 6, 6, 6); // creating the result tab QHBoxLayout* resultLabelLayout = new QHBoxLayout(); resultLabelLayout->setSpacing(6); resultLabelLayout->setContentsMargins(0, 0, 0, 0); foundLabel = new QLabel(resultTab); QSizePolicy foundpolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); foundpolicy.setHeightForWidth(foundLabel->sizePolicy().hasHeightForWidth()); foundLabel->setSizePolicy(foundpolicy); foundLabel->setFrameShape(QLabel::StyledPanel); foundLabel->setFrameShadow(QLabel::Sunken); foundLabel->setText(i18n("Found 0 matches.")); resultLabelLayout->addWidget(foundLabel); searchingLabel = new KSqueezedTextLabel(resultTab); searchingLabel->setFrameShape(QLabel::StyledPanel); searchingLabel->setFrameShadow(QLabel::Sunken); searchingLabel->setText(""); resultLabelLayout->addWidget(searchingLabel); resultLayout->addLayout(resultLabelLayout, 2, 0); // creating the result list view result = new SearchResultContainer(this); // the view resultView = KrViewFactory::createView(RESULTVIEW_TYPE, resultTab, krConfig); resultView->init(false); resultView->restoreSettings(KConfigGroup(&group, "ResultView")); resultView->setMainWindow(this); resultView->prepareForActive(); resultView->refreshColors(); resultView->setFiles(result); resultView->refresh(); resultLayout->addWidget(resultView->widget(), 0, 0); // search bar searchBar = new KrSearchBar(resultView, this); searchBar->hide(); resultLayout->addWidget(searchBar, 1, 0); QHBoxLayout* foundTextLayout = new QHBoxLayout(); foundTextLayout->setSpacing(6); foundTextLayout->setContentsMargins(0, 0, 0, 0); QLabel *l1 = new QLabel(resultTab); QSizePolicy l1policy(QSizePolicy::Minimum, QSizePolicy::Minimum); l1policy.setHeightForWidth(l1->sizePolicy().hasHeightForWidth()); l1->setSizePolicy(l1policy); l1->setFrameShape(QLabel::StyledPanel); l1->setFrameShadow(QLabel::Sunken); l1->setText(i18n("Text found:")); foundTextLayout->addWidget(l1); foundTextLabel = new KrSqueezedTextLabel(resultTab); foundTextLabel->setFrameShape(QLabel::StyledPanel); foundTextLabel->setFrameShadow(QLabel::Sunken); foundTextLabel->setText(""); foundTextLayout->addWidget(foundTextLabel); resultLayout->addLayout(foundTextLayout, 3, 0); searcherTabs->addTab(resultTab, i18n("&Results")); searchBaseLayout->addWidget(searcherTabs, 0, 0); // signals and slots connections connect(mainSearchBtn, SIGNAL(clicked()), this, SLOT(startSearch())); connect(mainStopBtn, SIGNAL(clicked()), this, SLOT(stopSearch())); connect(mainCloseBtn, SIGNAL(clicked()), this, SLOT(closeDialog())); connect(mainFeedToListBoxBtn, SIGNAL(clicked()), this, SLOT(feedToListBox())); connect(profileManager, SIGNAL(loadFromProfile(QString)), filterTabs, SLOT(loadFromProfile(QString))); connect(profileManager, SIGNAL(saveToProfile(QString)), filterTabs, SLOT(saveToProfile(QString))); connect(resultView->op(), SIGNAL(currentChanged(KrViewItem*)), SLOT(currentChanged(KrViewItem*))); connect(resultView->op(), SIGNAL(executed(QString)), SLOT(executed(QString))); connect(resultView->op(), SIGNAL(contextMenu(QPoint)), SLOT(contextMenu(QPoint))); // tab order setTabOrder(mainSearchBtn, mainCloseBtn); setTabOrder(mainCloseBtn, mainStopBtn); setTabOrder(mainStopBtn, searcherTabs); setTabOrder(searcherTabs, resultView->widget()); sizeX = group.readEntry("Window Width", -1); sizeY = group.readEntry("Window Height", -1); if (sizeX != -1 && sizeY != -1) resize(sizeX, sizeY); if (group.readEntry("Window Maximized", false)) showMaximized(); else show(); generalFilter->searchFor->setFocus(); // finaly, load a profile of apply defaults: if (profile.isEmpty()) { // load the last used values generalFilter->searchFor->setEditText(lastSearchText); generalFilter->searchFor->lineEdit()->selectAll(); generalFilter->ofType->setCurrentIndex(lastSearchType); generalFilter->searchForCase->setChecked(lastSearchForCase); generalFilter->containsWholeWord->setChecked(lastContainsWholeWord); generalFilter->containsTextCase->setChecked(lastContainsWithCase); generalFilter->containsRegExp->setChecked(lastContainsRegExp); generalFilter->searchInDirs->setChecked(lastSearchInSubDirs); generalFilter->searchInArchives->setChecked(lastSearchInArchives); generalFilter->followLinks->setChecked(lastFollowSymLinks); // the path in the active panel should be the default search location generalFilter->searchIn->lineEdit()->setText(ACTIVE_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)); } else profileManager->loadProfile(profile); // important: call this _after_ you've connected profileManager ot the loadFromProfile!! } KrSearchDialog::~KrSearchDialog() { delete query; query = 0; delete resultView; resultView = 0; } void KrSearchDialog::closeDialog(bool isAccept) { if(isBusy) { closed = true; return; } // stop the search if it's on-going if (searcher != 0) { delete searcher; searcher = 0; } // saving the searcher state KConfigGroup group(krConfig, "Search"); group.writeEntry("Window Width", sizeX); group.writeEntry("Window Height", sizeY); group.writeEntry("Window Maximized", isMaximized()); resultView->saveSettings(KConfigGroup(&group, "ResultView")); lastSearchText = generalFilter->searchFor->currentText(); lastSearchType = generalFilter->ofType->currentIndex(); lastSearchForCase = generalFilter->searchForCase->isChecked(); lastContainsWholeWord = generalFilter->containsWholeWord->isChecked(); lastContainsWithCase = generalFilter->containsTextCase->isChecked(); lastContainsRegExp = generalFilter->containsRegExp->isChecked(); lastSearchInSubDirs = generalFilter->searchInDirs->isChecked(); lastSearchInArchives = generalFilter->searchInArchives->isChecked(); lastFollowSymLinks = generalFilter->followLinks->isChecked(); hide(); SearchDialog = 0; if (isAccept) QDialog::accept(); else QDialog::reject(); this->deleteLater(); } void KrSearchDialog::reject() { closeDialog(false); } void KrSearchDialog::resizeEvent(QResizeEvent *e) { if (!isMaximized()) { sizeX = e->size().width(); sizeY = e->size().height(); } } void KrSearchDialog::slotFound(const FileItem &file, const QString &foundText) { result->addItem(file, foundText); foundLabel->setText(i18np("Found %1 match.", "Found %1 matches.", result->numFileItems())); } bool KrSearchDialog::gui2query() { // prepare the query ... /////////////////// names, locations and greps if (query != 0) { delete query; query = 0; } query = new KRQuery(); return filterTabs->fillQuery(query); } void KrSearchDialog::startSearch() { if(isBusy) return; // prepare the query ///////////////////////////////////////////// if (!gui2query()) return; // first, informative messages if (query->searchInArchives()) { KMessageBox::information(this, i18n("Since you chose to also search in archives, " "note the following limitations:\n" "You cannot search for text (grep) while doing" " a search that includes archives."), 0, "searchInArchives"); } // prepare the gui /////////////////////////////////////////////// mainSearchBtn->setEnabled(false); mainCloseBtn->setEnabled(false); mainStopBtn->setEnabled(true); mainFeedToListBoxBtn->setEnabled(false); result->clear(); resultView->setSortMode(KrViewProperties::NoColumn, 0); searchingLabel->setText(""); foundLabel->setText(i18n("Found 0 matches.")); searcherTabs->setCurrentIndex(2); // show the results page foundTextLabel->setText(""); isBusy = true; qApp->processEvents(); // start the search. if (searcher != 0) abort(); searcher = new KRSearchMod(query); connect(searcher, SIGNAL(searching(QString)), searchingLabel, SLOT(setText(QString))); connect(searcher, &KRSearchMod::found, this, &KrSearchDialog::slotFound); connect(searcher, SIGNAL(finished()), this, SLOT(stopSearch())); searcher->start(); isBusy = false; delete searcher; searcher = 0; // gui stuff mainSearchBtn->setEnabled(true); mainCloseBtn->setEnabled(true); mainStopBtn->setEnabled(false); if (result->numFileItems()) mainFeedToListBoxBtn->setEnabled(true); searchingLabel->setText(i18n("Finished searching.")); if (closed) closeDialog(); } void KrSearchDialog::stopSearch() { if (searcher != 0) { searcher->stop(); disconnect(searcher, 0, 0, 0); } } void KrSearchDialog::executed(const QString &name) { // 'name' is (local) file path or complete URL QString path = name; QString fileName; if(!name.endsWith('/')) { // not a directory, split filename and path int idx = name.lastIndexOf("/"); fileName = name.mid(idx+1); path = name.left(idx); } QUrl url(path); if (url.scheme().isEmpty()) url.setScheme("file"); ACTIVE_FUNC->openUrl(url, fileName); showMinimized(); } void KrSearchDialog::currentChanged(KrViewItem *item) { if(!item) return; QString text = result->foundText(item->getFileItem()); if(!text.isEmpty()) { // ugly hack: find the and in the text, then // use it to set the are which we don't want squeezed int idx = text.indexOf("") - 4; // take "" into account int length = text.indexOf("") - idx + 4; foundTextLabel->setText(text, idx, length); } } void KrSearchDialog::closeEvent(QCloseEvent *e) { /* if searching is in progress we must not close the window */ if (isBusy) /* because qApp->processEvents() is called by the searcher and */ { /* at window desruction, the searcher object will be deleted */ stopSearch(); /* instead we stop searching */ closed = true; /* and after stopping: startSearch can close the window */ e->ignore(); /* ignoring the close event */ } else QDialog::closeEvent(e); /* if no searching, let QDialog handle the event */ } void KrSearchDialog::keyPressEvent(QKeyEvent *e) { // TODO: don't use hardcoded shortcuts if (isBusy && e->key() == Qt::Key_Escape) { /* at searching we must not close the window */ stopSearch(); /* so we simply stop searching */ return; } if (resultView->widget()->hasFocus()) { if ((e->key() | e->modifiers()) == (Qt::CTRL | Qt::Key_I)) { searchBar->showBar(KrSearchBar::MODE_FILTER); } else if (e->key() == Qt::Key_F4) { tryPlaceSearchQueryToClipboard(); editCurrent(); return; } else if (e->key() == Qt::Key_F3) { tryPlaceSearchQueryToClipboard(); viewCurrent(); return; } else if (e->key() == Qt::Key_F10) { compareByContent(); return; } else if (KrGlobal::copyShortcut == QKeySequence(e->key() | e->modifiers())) { copyToClipBoard(); return; } } QDialog::keyPressEvent(e); } void KrSearchDialog::editCurrent() { KrViewItem *current = resultView->getCurrentKrViewItem(); if (current) KrViewer::edit(current->getFileItem()->getUrl(), this); } void KrSearchDialog::viewCurrent() { KrViewItem *current = resultView->getCurrentKrViewItem(); if (current) KrViewer::view(current->getFileItem()->getUrl(), this); } void KrSearchDialog::compareByContent() { KrViewItemList list; resultView->getSelectedKrViewItems(&list); if (list.count() != 2) return; SLOTS->compareContent(list[0]->getFileItem()->getUrl(),list[1]->getFileItem()->getUrl()); } void KrSearchDialog::contextMenu(const QPoint &pos) { // create the menu QMenu popup; popup.setTitle(i18n("Krusader Search")); QAction *actView = popup.addAction(i18n("View File (F3)")); QAction *actEdit = popup.addAction(i18n("Edit File (F4)")); QAction *actComp = popup.addAction(i18n("Compare by content (F10)")); if(resultView->numSelected() != 2) actComp->setEnabled(false); QAction *actClip = popup.addAction(i18n("Copy selected to clipboard")); QAction *result = popup.exec(pos); // check out the user's option if (result == actView) viewCurrent(); else if (result == actEdit) editCurrent(); else if (result == actClip) copyToClipBoard(); else if (result == actComp) compareByContent(); } void KrSearchDialog::feedToListBox() { VirtualFileSystem virtFilesystem; virtFilesystem.scanDir(QUrl::fromLocalFile("/")); KConfigGroup group(krConfig, "Search"); int listBoxNum = group.readEntry("Feed To Listbox Counter", 1); QString queryName; if(query) { QString where = KrServices::toStringList(query->searchInDirs()).join(", "); if(query->content().isEmpty()) queryName = i18n("Search results for \"%1\" in %2", query->nameFilter(), where); else queryName = i18n("Search results for \"%1\" containing \"%2\" in %3", query->nameFilter(), query->content(), where); } QString fileSystemName; do { fileSystemName = i18n("Search results") + QString(" %1").arg(listBoxNum++); } while (virtFilesystem.getFileItem(fileSystemName) != 0); group.writeEntry("Feed To Listbox Counter", listBoxNum); KConfigGroup ga(krConfig, "Advanced"); if (ga.readEntry("Confirm Feed to Listbox", _ConfirmFeedToListbox)) { bool ok; fileSystemName = QInputDialog::getText(this, i18n("Query name"), i18n("Here you can name the file collection"), QLineEdit::Normal, fileSystemName, &ok); if (! ok) return; } QList urlList; foreach(FileItem *fileitem, result->fileItems()) urlList.push_back(fileitem->getUrl()); mainSearchBtn->setEnabled(false); mainCloseBtn->setEnabled(false); mainFeedToListBoxBtn->setEnabled(false); isBusy = true; const QUrl url = QUrl(QString("virt:/") + fileSystemName); virtFilesystem.scanDir(url); virtFilesystem.addFiles(urlList); virtFilesystem.setMetaInformation(queryName); //ACTIVE_FUNC->openUrl(url); ACTIVE_MNG->slotNewTab(url); isBusy = false; closeDialog(); } void KrSearchDialog::copyToClipBoard() { QList urls; foreach(FileItem *fileitem, result->fileItems()) urls.push_back(fileitem->getUrl()); if (urls.count() == 0) return; QMimeData *mimeData = new QMimeData; mimeData->setImageData(FL_LOADICON("file")); mimeData->setUrls(urls); QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); } void KrSearchDialog::tryPlaceSearchQueryToClipboard() { if (searchTextToClipboard->isChecked() && !generalFilter->containsText->currentText().isEmpty() && QApplication::clipboard()->text() != generalFilter->containsText->currentText()) { QApplication::clipboard()->setText(generalFilter->containsText->currentText()); } } diff --git a/krusader/UserAction/expander.cpp b/krusader/UserAction/expander.cpp index e40de596..608b4be5 100644 --- a/krusader/UserAction/expander.cpp +++ b/krusader/UserAction/expander.cpp @@ -1,1215 +1,1215 @@ /***************************************************************************** * Copyright (C) 2004 Jonas Bähr * * Copyright (C) 2004 Shie Erlich * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "expander.h" #include "../krusader.h" #include "../krusaderview.h" #include "../panelmanager.h" #include "../Panel/listpanel.h" #include "../Panel/panelfunc.h" -#include "../Panel/krview.h" +#include "../Panel/PanelView/krview.h" #include "../Search/krsearchdialog.h" #include "../GUI/profilemanager.h" #include "../FileSystem/filesystemprovider.h" #include "../KViewer/krviewer.h" #include "../krservices.h" #ifdef SYNCHRONIZER_ENABLED #include "../Synchronizer/synchronizergui.h" #endif #ifdef __KJSEMBED__ #include "../KrJS/krjs.h" #endif // QtCore #include #include #include #include #include // QtGui #include // QtWidgets #include #include #include #include #include #include using namespace std; #define NEED_PANEL if (panel==0) { panelMissingError(_expression,exp); return QString(); } inline void exp_placeholder::setError(Expander& exp, const Error& e) { exp.setError(e); } inline QStringList exp_placeholder::splitEach(const TagString& s) { return Expander::splitEach(s); } inline exp_placeholder::exp_placeholder() { } void exp_placeholder::panelMissingError(const QString &s, Expander& exp) { exp.setError(Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Needed panel specification missing in expander %1", s))); } QStringList exp_placeholder::fileList(const KrPanel* const panel, const QString& type, const QString& mask, const bool omitPath, const bool useUrl, Expander& exp, const QString& error) { QStringList items; if (type.isEmpty() || type == "all") panel->view->getItemsByMask(mask, &items); else if (type == "files") panel->view->getItemsByMask(mask, &items, false, true); else if (type == "dirs") panel->view->getItemsByMask(mask, &items, true, false); else if (type == "selected") panel->view->getSelectedItems(&items); else { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: Bad argument to %1: %2 is not valid item specifier", error, type))); return QStringList(); } if (!omitPath) { // add the current path // translate to urls using filesystem QList list = panel->func->files()->getUrls(items); items.clear(); // parse everything to a single qstring foreach(const QUrl &url, list) { items.push_back(useUrl ? url.url() : url.path()); } } return items; } namespace { class exp_simpleplaceholder : public exp_placeholder { public: EXP_FUNC; virtual TagString expFunc(const KrPanel*, const QStringList&, const bool&, Expander&) const = 0; }; #define PLACEHOLDER_CLASS(name) \ class name : public exp_placeholder { \ public: \ name(); \ virtual TagString expFunc ( const KrPanel*, const TagStringList&, const bool&, Expander& ) const; \ }; #define SIMPLE_PLACEHOLDER_CLASS(name) \ class name : public exp_simpleplaceholder { \ public: \ using exp_simpleplaceholder::expFunc; \ name(); \ virtual TagString expFunc ( const KrPanel*, const QStringList&, const bool&, Expander& ) const; \ }; /** * expands %_Path% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the path of the specified panel */ SIMPLE_PLACEHOLDER_CLASS(exp_Path) /** * expands %_Count% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the number of items, which type is specified by the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_Count) /** * expands %_Filter% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the correspondend filter (ie: "*.cpp") */ SIMPLE_PLACEHOLDER_CLASS(exp_Filter) /** * expands %_Current% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the current item ( != the selected onec) */ SIMPLE_PLACEHOLDER_CLASS(exp_Current); /** * expands %_List% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with a list of items, which type is specified by the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_List); /** * expands %_ListFile% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate * the active, other, right or left panel) with the name of a temporary file, * containing a list of items, which type is specified by the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_ListFile); /** * expands %_Ask% ('_' is necessary because there is no panel needed) * with the return of an input-dialog */ SIMPLE_PLACEHOLDER_CLASS(exp_Ask); /** * This copies it's first Parameter to the clipboard */ PLACEHOLDER_CLASS(exp_Clipboard); /** * This selects all items by the mask given with the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_Select); /** * This changes the panel'spath to the value given with the first Parameter. */ SIMPLE_PLACEHOLDER_CLASS(exp_Goto); /** * This is equal to 'cp '. */ PLACEHOLDER_CLASS(exp_Copy); /** * This is equal to 'mv '. */ PLACEHOLDER_CLASS(exp_Move); #ifdef SYNCHRONIZER_ENABLED /** * This opens the synchronizer with a given profile */ SIMPLE_PLACEHOLDER_CLASS(exp_Sync); #endif /** * This opens the searchmodule with a given profile */ SIMPLE_PLACEHOLDER_CLASS(exp_NewSearch); /** * This loads the panel-profile with a given name */ SIMPLE_PLACEHOLDER_CLASS(exp_Profile); /** * This is setting marks in the string where he is later split up for each {all, selected, files, dirs} */ SIMPLE_PLACEHOLDER_CLASS(exp_Each); /** * This sets the sorting on a specific colunm */ SIMPLE_PLACEHOLDER_CLASS(exp_ColSort); /** * This sets relation between the left and right panel */ SIMPLE_PLACEHOLDER_CLASS(exp_PanelSize); #ifdef __KJSEMBED__ /** * This sets relation between the left and right panel */ SIMPLE_PLACEHOLDER_CLASS(exp_Script); #endif /** * This loads a file in the internal viewer */ SIMPLE_PLACEHOLDER_CLASS(exp_View); //////////////////////////////////////////////////////////// //////////////////////// utils //////////////////////// //////////////////////////////////////////////////////////// /** * escapes everything that confuses bash in filenames * @param s String to manipulate * @return escaped string */ QString bashquote(QString s) { /* // we _can_not_ use this function because it _encloses_ the sting in single-quots! // In this case quotes strings could not be concaternated anymore return KrServices::quote(s); */ static const QString evilstuff = "\\\"'`()[]{}!?;$&<>| \t\r\n"; // stuff that should get escaped for (int i = 0; i < evilstuff.length(); ++i) s.replace(evilstuff[ i ], ('\\' + evilstuff[ i ])); return s; } QString separateAndQuote(QStringList list, const QString& separator, const bool quote) { if (quote) transform(list.begin(), list.end(), list.begin(), bashquote); // QLineEdit::text() always escapes special characters, revert this for newline and tab QString decodedSeparator = separator; decodedSeparator.replace("\\n", "\n").replace("\\t", "\t"); return list.join(decodedSeparator); } ///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// expander classes //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// exp_Path::exp_Path() { _expression = "Path"; _description = i18n("Panel's Path..."); _needPanel = true; addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_Path::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL QString result; if (useUrl) result = panel->func->files()->currentDirectory().url() + '/'; else result = panel->func->files()->currentDirectory().path() + '/'; if (parameter.count() > 0 && parameter[0].toLower() == "no") // don't escape spaces return TagString(result); else return TagString(bashquote(result)); } exp_Count::exp_Count() { _expression = "Count"; _description = i18n("Number of..."); _needPanel = true; addParameter(exp_parameter(i18n("Count:"), "__choose:All;Files;Dirs;Selected", false)); } TagString exp_Count::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL int n = -1; if (parameter.count() == 0 || parameter[ 0 ].isEmpty() || parameter[ 0 ].toLower() == "all") n = panel->view->numDirs() + panel->view->numFiles(); else if (parameter[ 0 ].toLower() == "files") n = panel->view->numFiles(); else if (parameter[ 0 ].toLower() == "dirs") n = panel->view->numDirs(); else if (parameter[ 0 ].toLower() == "selected") n = panel->view->numSelected(); else { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: Bad argument to Count: %1 is not valid item specifier", parameter[0]))); return QString(); } return TagString(QString("%1").arg(n)); } exp_Filter::exp_Filter() { _expression = "Filter"; _description = i18n("Filter Mask (*.h, *.cpp, etc.)"); _needPanel = true; } TagString exp_Filter::expFunc(const KrPanel* panel, const QStringList&, const bool&, Expander& exp) const { NEED_PANEL return panel->view->filterMask().nameFilter(); } exp_Current::exp_Current() { _expression = "Current"; _description = i18n("Current File (!= Selected File)..."); _needPanel = true; addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_Current::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL QString item = panel->view->getCurrentItem(); QString result; if (parameter.count() > 0 && parameter[0].toLower() == "yes") // omit the current path result = item; else { QUrl url = panel->func->files()->getUrl(item); if (useUrl) result = url.url(); else result = url.path(); } if (parameter.count() > 1 && parameter[1].toLower() == "no") // don't escape spaces return result; else return bashquote(result); } exp_List::exp_List() { _expression = "List"; _description = i18n("Item List of..."); _needPanel = true; addParameter(exp_parameter(i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false)); addParameter(exp_parameter(i18n("Separator between the items (optional):"), " ", false)); addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Mask (optional, all but 'Selected'):"), "__select", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_List::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL // get selected items from view QStringList items; QString mask; if (parameter.count() <= 3 || parameter[3].isEmpty()) mask = '*'; else mask = parameter[3]; return separateAndQuote( fileList(panel, parameter.isEmpty() ? QString() : parameter[0].toLower(), mask, parameter.count() > 2 ? parameter[2].toLower() == "yes" : false, useUrl, exp, "List"), parameter.count() > 1 ? parameter[1] : " ", parameter.count() > 4 ? parameter[4].toLower() == "yes" : true); } exp_ListFile::exp_ListFile() { _expression = "ListFile"; _description = i18n("Filename of an Item List..."); _needPanel = true; addParameter(exp_parameter(i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false)); addParameter(exp_parameter(i18n("Separator between the items (optional)"), "\n", false)); addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Mask (optional, all but 'Selected'):"), "__select", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__no", false)); } TagString exp_ListFile::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL // get selected items from view QStringList items; QString mask; if (parameter.count() <= 3 || parameter[3].isEmpty()) mask = '*'; else mask = parameter[3]; QTemporaryFile tmpFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.itemlist")); tmpFile.setAutoRemove(false); if (!tmpFile.open()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_WORLD, i18n("Expander: temporary file could not be opened (%1)", tmpFile.errorString()))); return QString(); } QTextStream stream(&tmpFile); stream << separateAndQuote( fileList(panel, parameter.isEmpty() ? QString() : parameter[0].toLower(), mask, parameter.count() > 2 ? parameter[2].toLower() == "yes" : false, useUrl, exp, "ListFile"), parameter.count() > 1 ? parameter[1] : "\n", parameter.count() > 4 ? parameter[4].toLower() == "yes" : true) << "\n"; tmpFile.close(); return tmpFile.fileName(); } exp_Select::exp_Select() { _expression = "Select"; _description = i18n("Manipulate the Selection..."); _needPanel = true; addParameter(exp_parameter(i18n("Selection mask:"), "__select", true)); addParameter(exp_parameter(i18n("Manipulate in which way:"), "__choose:Set;Add;Remove", false)); } TagString exp_Select::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& , Expander& exp) const { NEED_PANEL KRQuery mask; if (parameter.count() <= 0 || parameter[0].isEmpty()) mask = KRQuery("*"); else mask = KRQuery(parameter[0]); if (parameter.count() > 1 && parameter[1].toLower() == "list-add") panel->view->select(mask); else if (parameter.count() > 1 && parameter[1].toLower() == "list-remove") panel->view->unselect(mask); else { // parameter[1].toLower() == "set" or isEmpty() or whatever panel->view->unselect(KRQuery("*")); panel->view->select(mask); } return QString(); // this doesn't return anything, that's normal! } exp_Goto::exp_Goto() { _expression = "Goto"; _description = i18n("Jump to a Location..."); _needPanel = true; addParameter(exp_parameter(i18n("Choose a path:"), "__goto", true)); addParameter(exp_parameter(i18n("Open location in a new tab"), "__no", false)); } TagString exp_Goto::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL bool newTab = false; if (parameter.count() > 1 && parameter[1].toLower() == "yes") newTab = true; if (parameter.count() == 0) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 1 parameter is required for Goto."))); return QString(); } QUrl url = QUrl::fromUserInput(parameter[0], QString(), QUrl::AssumeLocalFile); if (newTab) { if (panel == LEFT_PANEL) MAIN_VIEW->leftManager()->slotNewTab(url); else MAIN_VIEW->rightManager()->slotNewTab(url); } else { panel->func->openUrl(url, ""); panel->gui->slotFocusOnMe(); } return QString(); // this doesn't return anything, that's normal! } /* exp_Search::exp_Search() { _expression = "Search"; _description = i18n("Search for files"); _needPanel = true; addParameter( new exp_parameter( i18n("please choose the setting"), "__searchprofile", true ) ); addParameter( new exp_parameter( i18n("open the search in a new tab"), "__yes", false ) ); //TODO: add this also to panel-dependent as soon as filesystem support the display of search-results } */ exp_Ask::exp_Ask() { _expression = "Ask"; _description = i18n("Ask Parameter from User..."); _needPanel = false; addParameter(exp_parameter(i18n("Question:"), "Where do you want do go today?", true)); addParameter(exp_parameter(i18n("Preset (optional):"), "", false)); addParameter(exp_parameter(i18n("Caption (optional):"), "", false)); } TagString exp_Ask::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { QString caption, preset, result; if (parameter.count() == 0) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 1 parameter is required for Ask."))); return QString(); } if (parameter.count() <= 2 || parameter[2].isEmpty()) caption = i18n("User Action"); else caption = parameter[2]; if (parameter.count() <= 1 || parameter[1].isEmpty()) preset.clear(); else preset = parameter[1]; bool ok; result = QInputDialog::getText(krMainWindow, caption, parameter[0], QLineEdit::Normal, preset, &ok); if (ok) return result; else { setError(exp, Error(Error::exp_S_ERROR, Error::exp_C_USER, "User cancelled")); return QString(); } } exp_Clipboard::exp_Clipboard() { _expression = "Clipboard"; _description = i18n("Copy to Clipboard..."); _needPanel = false; addParameter(exp_parameter(i18n("What to copy:"), "__placeholder", true)); addParameter(exp_parameter(i18n("Append to current clipboard content with this separator (optional):"), "", false)); } TagString exp_Clipboard::expFunc(const KrPanel*, const TagStringList& parameter, const bool&, Expander& exp) const { // qDebug() << "Expander::exp_Clipboard, parameter[0]: '" << parameter[0] << "', Clipboard: " << QApplication::clipboard()->text() << endl; if (parameter.count() == 0) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 1 parameter is required for Clipboard."))); return QString(); } QStringList lst = splitEach(parameter[0]); if (parameter.count() > 1 && !parameter[1].isSimple()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Expander: %Each% may not be in the second argument of %Clipboard%"))); return QString(); } if (parameter.count() <= 1 || parameter[1].string().isEmpty() || QApplication::clipboard()->text().isEmpty()) QApplication::clipboard()->setText(lst.join("\n")); else QApplication::clipboard()->setText(QApplication::clipboard()->text() + parameter[1].string() + lst.join("\n")); return QString(); // this doesn't return anything, that's normal! } exp_Copy::exp_Copy() { _expression = "Copy"; _description = i18n("Copy a File/Folder..."); _needPanel = false; addParameter(exp_parameter(i18n("What to copy:"), "__placeholder", true)); addParameter(exp_parameter(i18n("Where to copy:"), "__placeholder", true)); } TagString exp_Copy::expFunc(const KrPanel*, const TagStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() < 2) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 2 parameter is required for Copy."))); return QString(); } // basically the parameter can already be used as URL, but since QUrl has problems with ftp-proxy-urls (like ftp://username@proxyusername@url...) this is neccesary: QStringList lst = splitEach(parameter[0]); if (!parameter[1].isSimple()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Expander: %Each% may not be in the second argument of %Copy%"))); return QString(); } QList src; for (QStringList::const_iterator it = lst.constBegin(), end = lst.constEnd();it != end;++it) src.push_back(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); // or transform(...) ? QUrl dest = QUrl::fromUserInput(parameter[1].string(), QString(), QUrl::AssumeLocalFile); if (!dest.isValid() || find_if(src.constBegin(), src.constEnd(), not1(mem_fun_ref(&QUrl::isValid))) != src.constEnd()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: invalid URLs in %_Copy(\"src\", \"dest\")%"))); return QString(); } FileSystemProvider::instance().startCopyFiles(src, dest); return QString(); // this doesn't return everything, that's normal! } exp_Move::exp_Move() { _expression = "Move"; _description = i18n("Move/Rename a File/Folder..."); _needPanel = false; addParameter(exp_parameter(i18n("What to move/rename:"), "__placeholder", true)); addParameter(exp_parameter(i18n("New target/name:"), "__placeholder", true)); } TagString exp_Move::expFunc(const KrPanel*, const TagStringList& parameter, const bool& , Expander& exp) const { if (parameter.count() < 2) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 2 parameter is required for Move."))); return QString(); } // basically the parameter can already be used as URL, but since QUrl has problems with ftp-proxy-urls (like ftp://username@proxyusername@url...) this is neccesary: QStringList lst = splitEach(parameter[0]); if (!parameter[1].isSimple()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("%Each% may not be in the second argument of %Move%"))); return QString(); } QList src; for (QStringList::const_iterator it = lst.constBegin(), end = lst.constEnd();it != end;++it) src.push_back(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); // or transform(...) ? QUrl dest = QUrl::fromUserInput(parameter[1].string(), QString(), QUrl::AssumeLocalFile); if (!dest.isValid() || find_if(src.constBegin(), src.constEnd(), not1(mem_fun_ref(&QUrl::isValid))) != src.constEnd()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: invalid URLs in %_Move(\"src\", \"dest\")%"))); return QString(); } FileSystemProvider::instance().startCopyFiles(src, dest, KIO::CopyJob::Move); return QString(); // this doesn't return anything, that's normal! } #ifdef SYNCHRONIZER_ENABLED exp_Sync::exp_Sync() { _expression = "Sync"; _description = i18n("Load a Synchronizer Profile..."); _needPanel = false; addParameter(exp_parameter(i18n("Choose a profile:"), "__syncprofile", true)); } TagString exp_Sync::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no profile specified for %_Sync(profile)%"))); return QString(); } new SynchronizerGUI(0, parameter[0]); return QString(); // this doesn't return everything, that's normal! } #endif exp_NewSearch::exp_NewSearch() { _expression = "NewSearch"; _description = i18n("Load a Searchmodule Profile..."); _needPanel = false; addParameter(exp_parameter(i18n("Choose a profile:"), "__searchprofile", true)); } TagString exp_NewSearch::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no profile specified for %_NewSearch(profile)%"))); return QString(); } new KrSearchDialog(parameter[0], krApp); return QString(); // this doesn't return everything, that's normal! } exp_Profile::exp_Profile() { _expression = "Profile"; _description = i18n("Load a Panel Profile..."); _needPanel = false; addParameter(exp_parameter(i18n("Choose a profile:"), "__panelprofile", true)); } TagString exp_Profile::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no profile specified for %_Profile(profile)%; abort..."))); return QString(); } MAIN_VIEW->profiles(parameter[0]); return QString(); // this doesn't return everything, that's normal! } exp_Each::exp_Each() { _expression = "Each"; _description = i18n("Separate Program Call for Each..."); _needPanel = true; addParameter(exp_parameter(i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false)); addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Mask (optional, all but 'Selected'):"), "__select", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_Each::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL QString mask; if (parameter.count() <= 2 || parameter[2].isEmpty()) mask = '*'; else mask = parameter[2]; TagString ret; QStringList l = fileList(panel, parameter.empty() ? QString() : parameter[0].toLower(), mask, parameter.count() > 1 && parameter[1].toLower() == "yes", useUrl, exp, "Each"); if (!(parameter.count() <= 3 || parameter[3].toLower() != "yes")) transform(l.begin(), l.end(), l.begin(), bashquote); ret.insertTag(0, l); return ret; } exp_ColSort::exp_ColSort() { _expression = "ColSort"; _description = i18n("Set Sorting for This Panel..."); _needPanel = true; addParameter(exp_parameter(i18n("Choose a column:"), "__choose:Name;Ext;Type;Size;Modified;Perms;rwx;Owner;Group", true)); addParameter(exp_parameter(i18n("Choose a sort sequence:"), "__choose:Toggle;Asc;Desc", false)); } TagString exp_ColSort::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no column specified for %_ColSort(column)%"))); return QString(); } KrViewProperties::ColumnType oldColumn = panel->view->properties()->sortColumn; KrViewProperties::ColumnType column = oldColumn; if (parameter[0].toLower() == "name") { column = KrViewProperties::Name; } else if (parameter[0].toLower() == "ext") { column = KrViewProperties::Ext; } else if (parameter[0].toLower() == "type") { column = KrViewProperties::Type; } else if (parameter[0].toLower() == "size") { column = KrViewProperties::Size; } else if (parameter[0].toLower() == "modified") { column = KrViewProperties::Modified; } else if (parameter[0].toLower() == "changed") { column = KrViewProperties::Changed; } else if (parameter[0].toLower() == "accessed") { column = KrViewProperties::Accessed; } else if (parameter[0].toLower() == "perms") { column = KrViewProperties::Permissions; } else if (parameter[0].toLower() == "rwx") { column = KrViewProperties::KrPermissions; } else if (parameter[0].toLower() == "owner") { column = KrViewProperties::Owner; } else if (parameter[0].toLower() == "group") { column = KrViewProperties::Group; } else { setError(exp, Error(Error::exp_S_WARNING, Error::exp_C_ARGUMENT, i18n("Expander: unknown column specified for %_ColSort(%1)%", parameter[0]))); return QString(); } bool descending = panel->view->properties()->sortOptions & KrViewProperties::Descending; if (parameter.count() <= 1 || (parameter[1].toLower() != "asc" && parameter[1].toLower() != "desc")) { // no sortdir parameter if(column == oldColumn) // reverse direction if column is unchanged descending = !descending; else // otherwise set to ascending descending = false; } else { // sortdir specified if (parameter[1].toLower() == "asc") descending = false; else // == desc descending = true; } panel->view->setSortMode(column, descending); return QString(); // this doesn't return anything, that's normal! } exp_PanelSize::exp_PanelSize() { _expression = "PanelSize"; _description = i18n("Set Relation Between the Panels..."); _needPanel = true; addParameter(exp_parameter(i18n("Set the new size in percent:"), "__int:0;100;5;50", true)); } TagString exp_PanelSize::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL int newSize; if (parameter.count() == 0 || parameter[0].isEmpty()) newSize = 50; //default is 50% else newSize = parameter[0].toInt(); if (newSize < 0 || newSize > 100) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: Value %1 out of range for %_PanelSize(percent)%. The first parameter has to be >0 and <100", newSize))); return QString(); } MAIN_VIEW->setPanelSize(panel->isLeft(), newSize); return QString(); // this doesn't return everything, that's normal! } #ifdef __KJSEMBED__ exp_Script::exp_Script() { _expression = "Script"; _description = i18n("Execute a JavaScript Extension..."); _needPanel = false; addParameter(exp_parameter(i18n("Location of the script"), "", true)); addParameter(exp_parameter(i18n("Set some variables for the execution (optional).\ni.e. \"return=return_var;foo=bar\", consult the handbook for more information"), "", false)); } TagString exp_Script::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no script specified for %_Script(script)%"))); return QString(); } QString filename = parameter[0]; if (filename.find('/') && QUrl::isRelativeUrl(filename)) { // this return the local version of the file if this exists. else the global one is returnd filename = locate("data", "krusader/js/" + filename); } if (! krJS) krJS = new KrJS(); KJS::ExecState *exec = krJS->globalExec(); QString jsReturn; if (parameter[1].toLower() == "yes") // to stay compatible with the old-style parameter jsReturn = "cmd"; else { QStringList jsVariables = parameter[1].split(';'); QString jsVariable, jsValue; for (QStringList::Iterator it = jsVariables.begin(); it != jsVariables.end(); ++it) { jsVariable = (*it).section('=', 0, 0).trimmed(); jsValue = (*it).section('=', 1); if (jsVariable == "return") jsReturn = jsValue.trimmed(); else krJS->putValue(jsVariable, KJSEmbed::convertToValue(exec, jsValue)); } } krJS->runFile(filename); if (! jsReturn.isEmpty()) return krJS->getValue(jsReturn).toString(krJS->globalExec()).qstring(); else return QString(); } #endif exp_View::exp_View() { _expression = "View"; _description = i18n("View File with Krusader's Internal Viewer..."); _needPanel = false; addParameter(exp_parameter(i18n("Which file to view (normally '%aCurrent%'):"), "__placeholder", true)); addParameter(exp_parameter(i18n("Choose a view mode:"), "__choose:generic;text;hex", false)); //addParameter( exp_parameter( i18n("Choose a window-mode"), "__choose:tab;window;panel", false ) ); //TODO: window-mode 'panel' should open the file in the third-hand viewer addParameter(exp_parameter(i18n("Choose a window mode:"), "__choose:tab;window", false)); } TagString exp_View::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no file to view in %_View(filename)%"))); return QString(); } QString viewMode, windowMode; if (parameter.count() <= 1 || parameter[1].isEmpty()) viewMode = "generic"; else viewMode = parameter[1]; if (parameter.count() <= 2 || parameter[2].isEmpty()) windowMode = "tab"; else windowMode = parameter[2]; KrViewer::Mode mode = KrViewer::Generic; if (viewMode == "text") mode = KrViewer::Text; else if (viewMode == "hex") mode = KrViewer::Hex; QUrl url = QUrl::fromUserInput(parameter[0], QString(), QUrl::AssumeLocalFile); KrViewer::view(url, mode, (windowMode == "window")); //TODO: Call the viewer with viewMode and windowMode. Filename is in parameter[0]. // It would be nice if parameter[0] could also be a space-separated filename-list (provided if the first parameter is %aList(selected)%) return QString(); // this doesn't return everything, that's normal! } ///////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// end of expander classes //////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// TagString exp_simpleplaceholder::expFunc(const KrPanel* p, const TagStringList& parameter, const bool& useUrl, Expander& exp) const { QStringList lst; for (TagStringList::const_iterator it = parameter.begin(), end = parameter.end();it != end;++it) if ((*it).isSimple()) lst.push_back((*it).string()); else { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("%Each% is not allowed in parameter to %1", description()))); return QString(); } return expFunc(p, lst, useUrl, exp); } } KrPanel* Expander::getPanel(const char panelIndicator, const exp_placeholder* pl, Expander& exp) { switch (panelIndicator) { case 'a': return ACTIVE_PANEL; case 'o': return OTHER_PANEL; case 'l': return LEFT_PANEL; case 'r': return RIGHT_PANEL; case '_': return 0; default: exp.setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Expander: Bad panel specifier %1 in placeholder %2", panelIndicator, pl->description()))); return 0; } } void Expander::expand(const QString& stringToExpand, bool useUrl) { TagString result = expandCurrent(stringToExpand, useUrl); if (error()) return; if (!result.isSimple()) resultList = splitEach(result); else resultList.append(result.string()); // krOut << resultList[0] << endl; } TagString Expander::expandCurrent(const QString& stringToExpand, bool useUrl) { TagString result; QString exp; TagString tmpResult; int begin, end, i; // int brackets = 0; // bool inQuotes = false; int idx = 0; while (idx < stringToExpand.length()) { if ((begin = stringToExpand.indexOf('%', idx)) == -1) break; if ((end = findEnd(stringToExpand, begin)) == -1) { // xgettext:no-c-format setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Error: unterminated % in Expander"))); return QString(); } result += stringToExpand.mid(idx, begin - idx); // copy until the start of %exp% // get the expression, and expand it using the correct expander function exp = stringToExpand.mid(begin + 1, end - begin - 1); // qDebug() << "------------- exp: '" << exp << "'" << endl; if (exp.isEmpty()) result += QString(QChar('%')); else { TagStringList parameter = separateParameter(&exp, useUrl); if (error()) return QString(); char panelIndicator = exp.toLower()[0].toLatin1(); exp.replace(0, 1, ""); for (i = 0; i < placeholderCount(); ++i) if (exp == placeholder(i)->expression()) { // qDebug() << "---------------------------------------" << endl; tmpResult = placeholder(i)->expFunc(getPanel(panelIndicator, placeholder(i), *this), parameter, useUrl, *this); if (error()) { return QString(); } else result += tmpResult; // qDebug() << "---------------------------------------" << endl; break; } if (i == placeholderCount()) { // didn't find an expander setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Error: unrecognized %%%1%2%% in Expander", panelIndicator, exp))); return QString(); } } //else idx = end + 1; } // copy the rest of the string result += stringToExpand.mid(idx); // qDebug() << "============== result '" << result << "'" << endl; return result; } QStringList Expander::splitEach(TagString stringToSplit) { if (stringToSplit.isSimple()) { // krOut << stringToSplit.string() << endl; QStringList l; l << stringToSplit.string(); return l; } pair pl = *stringToSplit.tagsBegin(); stringToSplit.eraseTag(stringToSplit.tagsBegin()); QStringList ret; for (QStringList::const_iterator it = pl.second.constBegin(), end = pl.second.constEnd();it != end;++it) { TagString s = stringToSplit; s.insert(pl.first, *it); ret += splitEach(s); } return ret; // qDebug() << "stringToSplit: " << stringToSplit << endl; } TagStringList Expander::separateParameter(QString* const exp, bool useUrl) { TagStringList parameter; QStringList parameter1; QString result; int begin, end; if ((begin = exp->indexOf('(')) != -1) { if ((end = exp->lastIndexOf(')')) == -1) { setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Error: missing ')' in Expander"))); return TagStringList(); } result = exp->mid(begin + 1, end - begin - 1); *exp = exp->left(begin); bool inQuotes = false; int idx = 0; begin = 0; while (idx < result.length()) { if (result[ idx ].toLatin1() == '\\') { if (result[ idx+1 ].toLatin1() == '"') result.replace(idx, 1, ""); } if (result[ idx ].toLatin1() == '"') inQuotes = !inQuotes; if (result[ idx ].toLatin1() == ',' && !inQuotes) { parameter1.append(result.mid(begin, idx - begin)); begin = idx + 1; // krOut << " ---- parameter: " << parameter.join(";") << endl; } idx++; } parameter1.append(result.mid(begin, idx - begin)); //don't forget the last one for (QStringList::Iterator it = parameter1.begin(); it != parameter1.end(); ++it) { *it = (*it).trimmed(); if ((*it).left(1) == "\"") *it = (*it).mid(1, (*it).length() - 2); parameter.push_back(expandCurrent(*it, useUrl)); if (error()) return TagStringList(); } } // krOut << "------- exp: " << *exp << " ---- parameter: " << parameter.join(";") << endl; return parameter; } int Expander::findEnd(const QString& str, int start) { int end = str.indexOf('%', start + 1); if (end == -1) return end; int bracket = str.indexOf('(', start + 1); if (end < bracket || bracket == -1) return end; int idx = bracket + 1; bool inQuotes = false; int depth = 1; while (idx < str.length()) { switch (str[ idx ].toLatin1()) { case '\\': idx ++; break; case '"': inQuotes = !inQuotes; break; case '(': if (!inQuotes) depth++; break; case ')': if (!inQuotes) --depth; break; case '%': if (depth == 0) return idx; } //switch idx++; } //while // failsafe return -1; } QList& Expander::_placeholder() { static QList ret; if(!ret.count()) { ret << new exp_View; ret << new exp_PanelSize; ret << new exp_ColSort; ret << new exp_Each; ret << new exp_Profile; ret << new exp_NewSearch; #ifdef SYNCHRONIZER_ENABLED ret << new exp_Sync; #endif ret << new exp_Move; ret << new exp_Copy; ret << new exp_Goto; ret << new exp_Select; ret << new exp_Clipboard; ret << new exp_Ask; ret << new exp_ListFile; ret << new exp_List; ret << new exp_Current; ret << new exp_Filter; ret << new exp_Count; ret << new exp_Path; #ifdef __KJSEMBED__ ret << new exp_Script; #endif } return ret; } diff --git a/krusader/UserAction/useraction.cpp b/krusader/UserAction/useraction.cpp index 49262246..dfbd445e 100644 --- a/krusader/UserAction/useraction.cpp +++ b/krusader/UserAction/useraction.cpp @@ -1,304 +1,304 @@ /***************************************************************************** * Copyright (C) 2004 Jonas Bähr * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "useraction.h" // QtCore #include #include #include #include #include #include // QtXml #include #include // QtWidgets #include #include #include #include #include #include "kraction.h" -#include "../krusader.h" -#include "../krusaderview.h" #include "../FileSystem/filesystem.h" +#include "../Panel/PanelView/krview.h" #include "../Panel/krpanel.h" -#include "../Panel/krview.h" #include "../Panel/panelfunc.h" +#include "../krusader.h" +#include "../krusaderview.h" UserAction::UserAction() { readAllFiles(); } UserAction::~UserAction() { // KrActions are deleted by Krusader's KActionCollection } void UserAction::removeKrAction(KrAction* action) { _actions.removeAll(action); if (_defaultActions.contains(action->objectName())) _deletedActions.insert(action->objectName()); } void UserAction::setAvailability() { setAvailability(ACTIVE_FUNC->files()->getUrl(ACTIVE_PANEL->view->getCurrentItem())); } void UserAction::setAvailability(const QUrl ¤tURL) { //qDebug() << "UserAction::setAvailability currendFile: " << currentURL.url() << endl; // disable the entries that should not appear in this folder QListIterator it(_actions); while (it.hasNext()) { KrAction * action = it.next(); action->setEnabled(action->isAvailable(currentURL)); } } void UserAction::populateMenu(KActionMenu* menu, const QUrl *currentURL) { // I have not found any method in Qt/KDE // for non-recursive searching of children by name ... QMap categoryMap; QList uncategorised; foreach(KrAction* action, _actions) { const QString category = action->category(); if (! action->isEnabled()) continue; if (currentURL != NULL && ! action->isAvailable(*currentURL)) continue; if (category.isEmpty()) { uncategorised.append(action); } else { if (! categoryMap.contains(category)) { KActionMenu *categoryMenu = new KActionMenu(category, menu); categoryMenu->setObjectName(category); categoryMap.insert(category, categoryMenu); } KActionMenu *targetMenu = categoryMap.value(category); targetMenu->addAction(action); } } QMutableMapIterator mapIter(categoryMap); while (mapIter.hasNext()) { mapIter.next(); menu->addAction(mapIter.value()); } foreach(KrAction* action, uncategorised) { menu->addAction(action); }; } QStringList UserAction::allCategories() { QStringList actionCategories; QListIterator it(_actions); while (it.hasNext()) { KrAction * action = it.next(); if (actionCategories.indexOf(action->category()) == -1) actionCategories.append(action->category()); } return actionCategories; } QStringList UserAction::allNames() { QStringList actionNames; QListIterator it(_actions); while (it.hasNext()) { KrAction * action = it.next(); actionNames.append(action->objectName()); } return actionNames; } void UserAction::readAllFiles() { QString filename = QStandardPaths::locate(QStandardPaths::GenericDataLocation, ACTION_XML); // locate returns the local file if it exists, else the global one is retrieved. if (! filename.isEmpty()) readFromFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, ACTION_XML), renameDoublicated); filename = QStandardPaths::locate(QStandardPaths::GenericDataLocation, ACTION_XML_EXAMPLES); if (! filename.isEmpty()) readFromFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, ACTION_XML_EXAMPLES), ignoreDoublicated); // ignore samples which are already in the normal file } void UserAction::readFromFile(const QString& filename, ReadMode mode, KrActionList* list) { QDomDocument* doc = new QDomDocument(ACTION_DOCTYPE); QFile file(filename); if (file.open(QIODevice::ReadOnly)) { //qDebug() << "UserAction::readFromFile - " << filename << "could be opened" << endl; if (! doc->setContent(&file)) { //qDebug() << "UserAction::readFromFile - content set - failed" << endl; // if the file doesn't exist till now, the content CAN be set but is empty. // if the content can't be set, the file exists and is NOT an xml-file. file.close(); delete doc; doc = 0; KMessageBox::error(MAIN_VIEW, i18n("The file %1 does not contain valid UserActions.\n", filename), // text i18n("UserActions - cannot read from file") // caption ); } file.close(); if (doc) { QDomElement root = doc->documentElement(); // check if the file has got the right root-element (ACTION_ROOT) // this finds out if the xml-file read to the DOM is really a krusader // useraction-file if (root.tagName() != ACTION_ROOT) { KMessageBox::error(MAIN_VIEW, i18n("The actionfile's root element is not called %1, using %2", QString::fromLatin1(ACTION_ROOT), filename), i18n("UserActions - cannot read from file") ); delete doc; doc = 0; } readFromElement(root, mode, list); delete doc; } } // if ( file.open( QIODevice::ReadOnly ) ) else { KMessageBox::error(MAIN_VIEW, i18n("Unable to open actions file %1", filename), i18n("UserActions - cannot read from file") ); } } void UserAction::readFromElement(const QDomElement& element, ReadMode mode, KrActionList* list) { for (QDomNode node = element.firstChild(); ! node.isNull(); node = node.nextSibling()) { QDomElement e = node.toElement(); if (e.isNull()) continue; // this should skip nodes which are not elements ( i.e. comments, , or text nodes) if (e.tagName() == "action") { QString name = e.attribute("name"); if (name.isEmpty()) { KMessageBox::error(MAIN_VIEW, i18n("Action without name detected. This action will not be imported.\nThis is an error in the file, you may want to correct it."), i18n("UserActions - invalid action") ); continue; } if (mode == ignoreDoublicated) { _defaultActions.insert(name); if (krApp->actionCollection()->action(name) || _deletedActions.contains(name)) continue; } QString basename = name + "_%1"; int i = 0; // appent a counter till the name is unique... (this checks every action, not only useractions) while (krApp->actionCollection()->action(name)) name = basename.arg(++i); KrAction* act = new KrAction(krApp->actionCollection(), name); if (act->xmlRead(e)) { _actions.append(act); if (list) list->append(act); } else delete act; } else if (e.tagName() == "deletedAction") { QString name = e.attribute("name"); if (name.isEmpty()) { krOut << "A deleted action without name detected! \nThis is an error in the file."; continue; } _deletedActions.insert(name); } } // for } QDomDocument UserAction::createEmptyDoc() { QDomDocument doc = QDomDocument(ACTION_DOCTYPE); // adding: doc.appendChild(doc.createProcessingInstruction("xml", ACTION_PROCESSINSTR)); //adding root-element doc.appendChild(doc.createElement(ACTION_ROOT)); // create new actionfile by adding a root-element ACTION_ROOT return doc; } bool UserAction::writeActionFile() { QString filename = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + ACTION_XML; QDomDocument doc = createEmptyDoc(); QDomElement root = doc.documentElement(); foreach(const QString &name, _deletedActions) { QDomElement element = doc.createElement("deletedAction"); element.setAttribute("name", name); root.appendChild(element); } QListIterator it(_actions); while (it.hasNext()) { KrAction * action = it.next(); root.appendChild(action->xmlDump(doc)); } return writeToFile(doc, filename); } bool UserAction::writeToFile(const QDomDocument& doc, const QString& filename) { QFile file(filename); if (! file.open(QIODevice::WriteOnly)) return false; /* // This is not needed, because each DomDocument created with UserAction::createEmptyDoc already contains the processinstruction if ( ! doc.firstChild().isProcessingInstruction() ) { // adding: if not already present QDomProcessingInstruction instr = doc.createProcessingInstruction( "xml", ACTION_PROCESSINSTR ); doc.insertBefore( instr, doc.firstChild() ); } */ QTextStream ts(&file); ts.setCodec("UTF-8"); ts << doc.toString(); file.close(); return true; } diff --git a/krusader/kractions.cpp b/krusader/kractions.cpp index 9c599ef4..eee4fdb9 100644 --- a/krusader/kractions.cpp +++ b/krusader/kractions.cpp @@ -1,331 +1,331 @@ /*************************************************************************** kractions.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "kractions.h" // QtWidgets #include #include #include #include #include #include #include #include #include "defaults.h" #include "krusader.h" #include "krusaderview.h" #include "krslots.h" #include "krtrashhandler.h" -#include "Panel/krviewfactory.h" -#include "GUI/krremoteencodingmenu.h" -#include "UserAction/useraction.h" -#include "MountMan/kmountman.h" #include "Dialogs/popularurls.h" +#include "GUI/krremoteencodingmenu.h" #include "JobMan/jobman.h" +#include "MountMan/kmountman.h" +#include "Panel/PanelView/krviewfactory.h" +#include "UserAction/useraction.h" QAction *KrActions::actCompare = 0; QAction *KrActions::actDiskUsage = 0; QAction *KrActions::actHomeTerminal = 0; QAction *KrActions::actRemoteEncoding = 0; QAction *KrActions::actProfiles = 0; QAction *KrActions::actMultiRename = 0; QAction *KrActions::actMountMan = 0; QAction *KrActions::actNewTool = 0; QAction *KrActions::actKonfigurator = 0; QAction *KrActions::actToolsSetup = 0; QAction *KrActions::actSwapPanels = 0; QAction *KrActions::actSwapSides = 0; QAction *KrActions::actFind = 0; QAction *KrActions::actLocate = 0; QAction *KrActions::actSwitchFullScreenTE = 0; QAction *KrActions::actAddBookmark = 0; QAction *KrActions::actSavePosition = 0; QAction *KrActions::actSelectColorMask = 0; QAction *KrActions::actOpenLeftBm = 0; QAction *KrActions::actOpenRightBm = 0; QAction *KrActions::actCmdlinePopup = 0; QAction *KrActions::actSplit = 0; QAction *KrActions::actCombine = 0; QAction *KrActions::actUserMenu = 0; QAction *KrActions::actManageUseractions = 0; #ifdef SYNCHRONIZER_ENABLED QAction *KrActions::actSyncDirs = 0; #endif QAction *KrActions::actF10 = 0; QAction *KrActions::actEmptyTrash = 0; QAction *KrActions::actTrashBin = 0; QAction *KrActions::actPopularUrls = 0; KToggleAction *KrActions::actToggleTerminal = 0; QAction *KrActions::actVerticalMode = 0; QAction *KrActions::actSelectNewerAndSingle = 0; QAction *KrActions::actSelectSingle = 0; QAction *KrActions::actSelectNewer = 0; QAction *KrActions::actSelectDifferentAndSingle = 0; QAction *KrActions::actSelectDifferent = 0; QAction **KrActions::compareArray[] = {&actSelectNewerAndSingle, &actSelectNewer, &actSelectSingle, &actSelectDifferentAndSingle, &actSelectDifferent, 0 }; QAction *KrActions::actExecStartAndForget = 0; QAction *KrActions::actExecCollectSeparate = 0; QAction *KrActions::actExecCollectTogether = 0; QAction *KrActions::actExecTerminalExternal = 0; QAction *KrActions::actExecTerminalEmbedded = 0; QAction **KrActions::execTypeArray[] = {&actExecStartAndForget, &actExecCollectSeparate, &actExecCollectTogether, &actExecTerminalExternal, &actExecTerminalEmbedded, 0 }; KToggleAction *KrActions::actToggleFnkeys = 0; KToggleAction *KrActions::actToggleCmdline = 0; KToggleAction *KrActions::actShowStatusBar = 0; KToggleAction *KrActions::actToggleHidden = 0; KToggleAction *KrActions::actCompareDirs = 0; QAction *KrActions::actJobProgress = 0; QAction *KrActions::actJobControl = 0; QAction *KrActions::actJobMode = 0; QAction *KrActions::actJobUndo = 0; #ifdef __KJSEMBED__ static QAction *actShowJSConsole; #endif QAction *createAction(QString text, QString icon, QKeySequence shortcut, QObject *recv, const char *slot, QString name, Krusader *krusaderApp) { QAction *a; if (icon.isEmpty()) a = new QAction(text, krusaderApp); else a = new QAction(QIcon::fromTheme(icon), text, krusaderApp); krusaderApp->connect(a, SIGNAL(triggered(bool)), recv, slot); krusaderApp->actionCollection()->addAction(name, a); krusaderApp->actionCollection()->setDefaultShortcut(a, shortcut); return a; } QAction *createAction(QString text, QString icon, QList shortcuts, QObject *recv, const char *slot, QString name, Krusader *krusaderApp) { QAction *a; if (icon.isEmpty()) a = new QAction(text, krusaderApp); else a = new QAction(QIcon::fromTheme(icon), text, krusaderApp); krusaderApp->connect(a, SIGNAL(triggered(bool)), recv, slot); krusaderApp->actionCollection()->addAction(name, a); krusaderApp->actionCollection()->setDefaultShortcuts(a, shortcuts); return a; } KToggleAction *createToggleAction(QString text, QString icon, QKeySequence shortcut, QObject *recv, const char *slot, QString name, Krusader *krusaderApp) { KToggleAction *a; if (icon == 0) a = new KToggleAction(text, krusaderApp); else a = new KToggleAction(QIcon::fromTheme(icon), text, krusaderApp); krusaderApp->connect(a, SIGNAL(triggered(bool)), recv, slot); krusaderApp->actionCollection()->addAction(name, a); krusaderApp->actionCollection()->setDefaultShortcut(a, shortcut); return a; } void KrActions::setupActions(Krusader *krusaderApp) { #define NEW_KACTION(VAR, TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME) \ VAR = createAction(TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME, krusaderApp); #define NEW_KTOGGLEACTION(VAR, TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME) \ VAR = createToggleAction(TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME, krusaderApp); // first come the TODO actions //actSync = 0;//new QAction(i18n("S&ynchronize Dirs"), 0, krusaderApp, 0, actionCollection(), "sync dirs"); //actNewTool = 0;//new QAction(i18n("&Add a new tool"), 0, krusaderApp, 0, actionCollection(), "add tool"); //actToolsSetup = 0;//new QAction(i18n("&Tools Menu Setup"), 0, 0, krusaderApp, 0, actionCollection(), "tools setup"); //KStandardAction::print(SLOTS, 0,actionCollection(),"std_print"); //KStandardAction::showMenubar( SLOTS, SLOT(showMenubar()), actionCollection(), "std_menubar" ); /* Shortcut disabled because of the Terminal Emulator bug. */ KConfigGroup group(krConfig, "Private"); int compareMode = group.readEntry("Compare Mode", 0); int cmdExecMode = group.readEntry("Command Execution Mode", 0); QAction *tmp; Q_UNUSED(tmp); NEW_KACTION(tmp, i18n("Tab-Switch panel"), 0, Qt::Key_Tab, MAIN_VIEW, SLOT(panelSwitch()), "tab"); KToggleToolBarAction *actShowToolBar = new KToggleToolBarAction(krusaderApp->toolBar(), i18n("Show Main Toolbar"), krusaderApp); krusaderApp->actionCollection()->addAction(KStandardAction::name(KStandardAction::ShowToolbar), actShowToolBar); KToggleToolBarAction *actShowJobToolBar = new KToggleToolBarAction(krusaderApp->toolBar("jobToolBar"), i18n("Show Job Toolbar"), krusaderApp); krusaderApp->actionCollection()->addAction("toggle show jobbar", actShowJobToolBar); KToggleToolBarAction *actShowActionsToolBar = new KToggleToolBarAction(krusaderApp->toolBar("actionsToolBar"), i18n("Show Actions Toolbar"), krusaderApp); krusaderApp->actionCollection()->addAction("toggle actions toolbar", actShowActionsToolBar); actShowStatusBar = KStandardAction::showStatusbar(SLOTS, SLOT(updateStatusbarVisibility()), krusaderApp->actionCollection()); KStandardAction::quit(krusaderApp, SLOT(quit()), krusaderApp->actionCollection()); KStandardAction::configureToolbars(krusaderApp, SLOT(configureToolbars()), krusaderApp->actionCollection()); KStandardAction::keyBindings(krusaderApp->guiFactory(), SLOT(configureShortcuts()), krusaderApp->actionCollection()); // the toggle actions NEW_KTOGGLEACTION(actToggleFnkeys, i18n("Show &FN Keys Bar"), 0, 0, SLOTS, SLOT(toggleFnkeys()), "toggle fn bar"); NEW_KTOGGLEACTION(actToggleCmdline, i18n("Show &Command Line"), 0, 0, SLOTS, SLOT(toggleCmdline()), "toggle command line"); NEW_KTOGGLEACTION(actToggleTerminal, i18n("Show &Embedded Terminal"), 0, Qt::ALT + Qt::CTRL + Qt::Key_T, SLOTS, SLOT(toggleTerminal()), "toggle terminal emulator"); NEW_KTOGGLEACTION(actToggleHidden, i18n("Show &Hidden Files"), 0, Qt::ALT + Qt::Key_Period, SLOTS, SLOT(showHiddenFiles(bool)), "toggle hidden files"); NEW_KACTION(actSwapPanels, i18n("S&wap Panels"), 0, Qt::CTRL + Qt::Key_U, SLOTS, SLOT(swapPanels()), "swap panels"); NEW_KACTION(actEmptyTrash, i18n("Empty Trash"), "trash-empty", 0, SLOTS, SLOT(emptyTrash()), "emptytrash"); NEW_KACTION(actTrashBin, i18n("Trash Popup Menu"), KrTrashHandler::trashIcon(), 0, SLOTS, SLOT(trashPopupMenu()), "trashbin"); NEW_KACTION(actSwapSides, i18n("Sw&ap Sides"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_U, SLOTS, SLOT(toggleSwapSides()), "toggle swap sides"); actToggleHidden->setChecked(KConfigGroup(krConfig, "Look&Feel").readEntry("Show Hidden", _ShowHidden)); // and then the DONE actions NEW_KACTION(actCmdlinePopup, i18n("popup cmdline"), 0, Qt::CTRL + Qt::Key_Slash, SLOTS, SLOT(cmdlinePopup()), "cmdline popup"); NEW_KACTION(tmp, i18n("Start &Root Mode Krusader"), "krusader_root", Qt::ALT + Qt::SHIFT + Qt::Key_K, SLOTS, SLOT(rootKrusader()), "root krusader"); NEW_KACTION(actProfiles, i18n("Pro&files"), "user-identity", Qt::ALT + Qt::SHIFT + Qt::Key_L, MAIN_VIEW, SLOT(profiles()), "profile"); NEW_KACTION(actSplit, i18n("Sp&lit File..."), "split", Qt::CTRL + Qt::Key_P, SLOTS, SLOT(slotSplit()), "split"); NEW_KACTION(actCombine, i18n("Com&bine Files..."), "kr_combine", 0, SLOTS, SLOT(slotCombine()), "combine"); NEW_KACTION(actSelectNewerAndSingle, i18n("&Select Newer and Single"), 0, 0, SLOTS, SLOT(compareSetup()), "select_newer_and_single"); NEW_KACTION(actSelectNewer, i18n("Select &Newer"), 0, 0, SLOTS, SLOT(compareSetup()), "select_newer"); NEW_KACTION(actSelectSingle, i18n("Select &Single"), 0, 0, SLOTS, SLOT(compareSetup()), "select_single"); NEW_KACTION(actSelectDifferentAndSingle, i18n("Select Different &and Single"), 0, 0, SLOTS, SLOT(compareSetup()), "select_different_and_single"); NEW_KACTION(actSelectDifferent, i18n("Select &Different"), 0, 0, SLOTS, SLOT(compareSetup()), "select_different"); actSelectNewerAndSingle->setCheckable(true); actSelectNewer->setCheckable(true); actSelectSingle->setCheckable(true); actSelectDifferentAndSingle->setCheckable(true); actSelectDifferent->setCheckable(true); QActionGroup *selectGroup = new QActionGroup(krusaderApp); selectGroup->setExclusive(true); selectGroup->addAction(actSelectNewerAndSingle); selectGroup->addAction(actSelectNewer); selectGroup->addAction(actSelectSingle); selectGroup->addAction(actSelectDifferentAndSingle); selectGroup->addAction(actSelectDifferent); if (compareMode < (int)(sizeof(compareArray) / sizeof(QAction **)) - 1) (*compareArray[ compareMode ])->setChecked(true); NEW_KACTION(actExecStartAndForget, i18n("Start and &Forget"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_start_and_forget"); NEW_KACTION(actExecCollectSeparate, i18n("Display &Separated Standard and Error Output"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_collect_separate"); NEW_KACTION(actExecCollectTogether, i18n("Display &Mixed Standard and Error Output"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_collect_together"); NEW_KACTION(actExecTerminalExternal, i18n("Start in &New Terminal"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_terminal_external"); NEW_KACTION(actExecTerminalEmbedded, i18n("Send to &Embedded Terminal Emulator"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_terminal_embedded"); actExecStartAndForget->setCheckable(true); actExecCollectSeparate->setCheckable(true); actExecCollectTogether->setCheckable(true); actExecTerminalExternal->setCheckable(true); actExecTerminalEmbedded->setCheckable(true); QActionGroup *actionGroup = new QActionGroup(krusaderApp); actionGroup->setExclusive(true); actionGroup->addAction(actExecStartAndForget); actionGroup->addAction(actExecCollectSeparate); actionGroup->addAction(actExecCollectTogether); actionGroup->addAction(actExecTerminalExternal); actionGroup->addAction(actExecTerminalEmbedded); if (cmdExecMode < (int)(sizeof(execTypeArray) / sizeof(QAction **)) - 1) (*execTypeArray[ cmdExecMode ])->setChecked(true); NEW_KACTION(actHomeTerminal, i18n("Start &Terminal"), "utilities-terminal", 0, SLOTS, SLOT(homeTerminal()), "terminal@home"); actMountMan = krMtMan.action(); krusaderApp->actionCollection()->addAction("mountman", actMountMan); krusaderApp->actionCollection()->setDefaultShortcut(actMountMan, Qt::ALT + Qt::Key_Slash); NEW_KACTION(actFind, i18n("&Search..."), "system-search", Qt::CTRL + Qt::Key_S, SLOTS, SLOT(search()), "find"); NEW_KACTION(actLocate, i18n("&Locate..."), "edit-find", Qt::SHIFT + Qt::CTRL + Qt::Key_L, SLOTS, SLOT(locate()), "locate"); #ifdef SYNCHRONIZER_ENABLED NEW_KACTION(actSyncDirs, i18n("Synchronize Fol&ders..."), "folder-sync", Qt::CTRL + Qt::Key_Y, SLOTS, SLOT(slotSynchronizeDirs()), "sync dirs"); #endif NEW_KACTION(actDiskUsage, i18n("D&isk Usage..."), "kr_diskusage", Qt::ALT + Qt::SHIFT + Qt::Key_S, SLOTS, SLOT(slotDiskUsage()), "disk usage"); NEW_KACTION(actKonfigurator, i18n("Configure &Krusader..."), "configure", 0, SLOTS, SLOT(startKonfigurator()), "konfigurator"); NEW_KACTION(actSavePosition, i18n("Save &Position"), 0, 0, krusaderApp, SLOT(savePosition()), "save position"); NEW_KACTION(actCompare, i18n("Compare b&y Content..."), "kr_comparedirs", 0, SLOTS, SLOT(compareContent()), "compare"); NEW_KACTION(actMultiRename, i18n("Multi &Rename..."), "edit-rename", Qt::SHIFT + Qt::Key_F9, SLOTS, SLOT(multiRename()), "multirename"); NEW_KACTION(actAddBookmark, i18n("Add Bookmark"), "bookmark-new", KStandardShortcut::addBookmark(), SLOTS, SLOT(addBookmark()), "add bookmark"); NEW_KACTION(actVerticalMode, i18n("Vertical Mode"), "view-split-top-bottom", Qt::ALT + Qt::CTRL + Qt::Key_R, MAIN_VIEW, SLOT(toggleVerticalMode()), "toggle vertical mode"); actUserMenu = new KActionMenu(i18n("User&actions"), krusaderApp); krusaderApp->actionCollection()->addAction("useractionmenu", actUserMenu); NEW_KACTION(actManageUseractions, i18n("Manage User Actions..."), 0, 0, SLOTS, SLOT(manageUseractions()), "manage useractions"); actRemoteEncoding = new KrRemoteEncodingMenu(i18n("Select Remote Charset"), "character-set", krusaderApp->actionCollection()); NEW_KACTION(actF10, i18n("Quit"), 0, Qt::Key_F10, krusaderApp, SLOT(quit()) , "F10_Quit"); NEW_KACTION(actPopularUrls, i18n("Popular URLs..."), 0, Qt::CTRL + Qt::Key_Z, krusaderApp->popularUrls(), SLOT(showDialog()), "Popular_Urls"); NEW_KACTION(actSwitchFullScreenTE, i18n("Toggle Fullscreen Embedded Terminal"), 0, Qt::CTRL + Qt::ALT + Qt::Key_F, MAIN_VIEW, SLOT(toggleFullScreenTerminalEmulator()), "switch_fullscreen_te"); NEW_KACTION(tmp, i18n("Move Focus Up"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Up, MAIN_VIEW, SLOT(focusUp()), "move_focus_up"); NEW_KACTION(tmp, i18n("Move Focus Down"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Down, MAIN_VIEW, SLOT(focusDown()), "move_focus_down"); // job manager actions actJobControl = krJobMan->controlAction(); krusaderApp->actionCollection()->addAction("job control", actJobControl); krusaderApp->actionCollection()->setDefaultShortcut(actJobControl, Qt::CTRL + Qt::ALT + Qt::Key_P); actJobProgress = krJobMan->progressAction(); krusaderApp->actionCollection()->addAction("job progress", actJobProgress); actJobMode = krJobMan->modeAction(); krusaderApp->actionCollection()->addAction("job mode", actJobMode); actJobUndo = krJobMan->undoAction(); krusaderApp->actionCollection()->addAction("job undo", actJobUndo); krusaderApp->actionCollection()->setDefaultShortcut(actJobUndo, Qt::CTRL + Qt::ALT + Qt::Key_Z); // and at last we can set the tool-tips actKonfigurator->setToolTip(i18n("Setup Krusader the way you like it")); actFind->setToolTip(i18n("Search for files")); // setup all UserActions krUserAction = new UserAction(); #ifdef __KJSEMBED__ actShowJSConsole = new QAction(i18n("JavaScript Console..."), Qt::ALT + Qt::CTRL + Qt::Key_J, SLOTS, SLOT(jsConsole()), krusaderApp->actionCollection(), "JS_Console"); #endif } diff --git a/krusader/krslots.cpp b/krusader/krslots.cpp index fe21a56f..80f14d8d 100644 --- a/krusader/krslots.cpp +++ b/krusader/krslots.cpp @@ -1,753 +1,753 @@ /*************************************************************************** krslots.cpp ------------------- copyright : (C) 2001 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krslots.h" // QtCore #include #include #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #ifdef __KJSEMBED__ #include #include "KrJS/krjs.h" #endif #include "defaults.h" #include "kractions.h" #include "krservices.h" #include "krtrashhandler.h" #include "krusader.h" #include "krusaderview.h" -#include "krview.h" #include "panelmanager.h" #include "ActionMan/actionman.h" #include "BookMan/krbookmarkbutton.h" #include "BookMan/krbookmarkhandler.h" #include "Dialogs/krdialogs.h" #include "Dialogs/krspecialwidgets.h" #include "Dialogs/krspwidgets.h" #include "DiskUsage/diskusagegui.h" #include "FileSystem/fileitem.h" #include "FileSystem/filesystem.h" #include "FileSystem/krquery.h" #include "GUI/dirhistorybutton.h" #include "GUI/kcmdline.h" #include "GUI/kfnkeys.h" #include "GUI/krusaderstatus.h" #include "GUI/mediabutton.h" #include "GUI/terminaldock.h" -#include "Konfigurator/konfigurator.h" #include "KViewer/krviewer.h" +#include "Konfigurator/konfigurator.h" #include "Locate/locate.h" #include "MountMan/kmountman.h" -#include "Panel/krviewfactory.h" -#include "Panel/krviewitem.h" -#include "Panel/krselectionmode.h" +#include "Panel/PanelView/krselectionmode.h" +#include "Panel/PanelView/krview.h" +#include "Panel/PanelView/krviewfactory.h" +#include "Panel/PanelView/krviewitem.h" #include "Panel/listpanel.h" #include "Panel/panelfunc.h" #include "Panel/panelpopup.h" -#include "Search/krsearchmod.h" #include "Search/krsearchdialog.h" +#include "Search/krsearchmod.h" #include "Splitter/combiner.h" -#include "Splitter/splittergui.h" #include "Splitter/splitter.h" +#include "Splitter/splittergui.h" #ifdef SYNCHRONIZER_ENABLED #include "Synchronizer/synchronizergui.h" #endif #define ACTIVE_VIEW _mainWindow->activeView() KRslots::KRslots(QObject *parent) : QObject(parent), _mainWindow(krApp) { } void KRslots::sendFileByEmail(const QList &urls) { if (urls.count() == 0) { KMessageBox::error(0, i18n("No selected files to send.")); return; } QString mailProg; QStringList lst = KrServices::supportedTools(); if (lst.contains("MAIL")) mailProg = lst[lst.indexOf("MAIL") + 1]; else { KMessageBox::error(0, i18n("Krusader cannot find a supported mail client. Please install one to your path. Hint: Krusader supports KMail.")); return; } QString subject, separator; foreach(const QUrl &url, urls) { subject += separator + url.fileName(); separator = ','; } subject = i18np("Sending file: %2", "Sending files: %2", urls.count(), subject); KProcess proc; QString executable = QUrl::fromLocalFile(mailProg).fileName(); if (executable == QStringLiteral("kmail")) { proc << mailProg << "--subject" << subject; foreach(const QUrl &url2, urls) proc << "--attach" << url2.toDisplayString(); } else if (executable == QStringLiteral("thunderbird")) { QString param = "attachment=\'"; separator = ""; foreach(const QUrl &url2, urls) { param += separator + url2.toDisplayString(); separator = ','; } param += "\',subject=\'" + subject + "\'"; proc << mailProg << "--compose" << param; } else if (executable == QStringLiteral("evolution")) { QString param = "mailto:?cc=&subject=" + subject + "&attach="; separator = ""; foreach(const QUrl &url2, urls) { param += separator + url2.toDisplayString(); separator = "&attach="; } proc << mailProg << param + ""; } if (!proc.startDetached()) KMessageBox::error(0, i18n("Error executing %1.", mailProg)); } void KRslots::compareContent() { const QStringList lstLeft = LEFT_PANEL->getSelectedNames(); const QStringList lstRight = RIGHT_PANEL->getSelectedNames(); const QStringList lstActive = ACTIVE_PANEL->gui->isLeft() ? lstLeft : lstRight; QUrl name1, name2; if (lstLeft.count() == 1 && lstRight.count() == 1) { // first, see if we've got exactly 1 selected file in each panel: name1 = LEFT_PANEL->func->files()->getUrl(lstLeft[0]); name2 = RIGHT_PANEL->func->files()->getUrl(lstRight[0]); } else if (lstActive.count() == 2) { // next try: are in the current panel exacty 2 files selected? name1 = ACTIVE_PANEL->func->files()->getUrl(lstActive[0]); name2 = ACTIVE_PANEL->func->files()->getUrl(lstActive[1]); } else if (ACTIVE_PANEL->otherPanel()->func->files()->getFileItem(ACTIVE_VIEW->getCurrentItem())) { // next try: is in the other panel a file with the same name? name1 = ACTIVE_PANEL->func->files()->getUrl(ACTIVE_VIEW->getCurrentItem()); name2 = ACTIVE_PANEL->otherPanel()->func->files()->getUrl(ACTIVE_VIEW->getCurrentItem()); } else { // if we got here, then we can't be sure what file to diff KMessageBox::detailedError(0, i18n("Do not know which files to compare."), "" + i18n("To compare two files by content, you can either:
  • Select one file in the left panel, and one in the right panel.
  • Select exactly two files in the active panel.
  • Make sure there is a file in the other panel, with the same name as the current file in the active panel.
") + "
"); return; } // else implied: all ok, let's call an external program to compare files // but if any of the files isn't local, download it first compareContent(name1, name2); } bool downloadToTemp(const QUrl &url, QString &dest) { QTemporaryFile tmpFile; tmpFile.setAutoRemove(false); if (tmpFile.open()) { dest = tmpFile.fileName(); KIO::Job* job = KIO::file_copy(url, QUrl::fromLocalFile(dest), -1, KIO::Overwrite | KIO::HideProgressInfo); if(!job->exec()) { KMessageBox::error(krApp, i18n("Krusader is unable to download %1", url.fileName())); return false; } return true; } return false; } void KRslots::compareContent(QUrl url1, QUrl url2) { QString diffProg; QStringList lst = KrServices::supportedTools(); if (lst.contains("DIFF")) diffProg = lst[lst.indexOf("DIFF") + 1]; else { KMessageBox::error(0, i18n("Krusader cannot find any of the supported diff-frontends. Please install one to your path. Hint: Krusader supports Kompare, KDiff3 and Xxdiff.")); return; } QString tmp1; QString tmp2; // kdiff3 sucks with spaces if (QUrl::fromLocalFile(diffProg).fileName() == "kdiff3" && !url1.toDisplayString().contains(" ") && !url2.toDisplayString().contains(" ")) { tmp1 = url1.toDisplayString(); tmp2 = url2.toDisplayString(); } else { if (!url1.isLocalFile()) { if (!downloadToTemp(url1, tmp1)) { return; } } else tmp1 = url1.path(); if (!url2.isLocalFile()) { if (!downloadToTemp(url2, tmp2)) { if (tmp1 != url1.path()) QFile::remove(tmp1); return; } } else tmp2 = url2.path(); } KrProcess *p = new KrProcess(tmp1 != url1.path() ? tmp1 : QString(), tmp2 != url2.path() ? tmp2 : QString()); *p << diffProg << tmp1 << tmp2; p->start(); if (!p->waitForStarted()) KMessageBox::error(0, i18n("Error executing %1.", diffProg)); } // GUI toggle slots void KRslots::toggleFnkeys() { if (MAIN_VIEW->fnKeys()->isVisible()) MAIN_VIEW->fnKeys()->hide(); else MAIN_VIEW->fnKeys()->show(); } void KRslots::toggleCmdline() { if (MAIN_VIEW->cmdLine()->isVisible()) MAIN_VIEW->cmdLine()->hide(); else MAIN_VIEW->cmdLine()->show(); } void KRslots::updateStatusbarVisibility() { krApp->statusBar()->setVisible(KrActions::actShowStatusBar->isChecked()); } void KRslots::toggleTerminal() { MAIN_VIEW->setTerminalEmulator(KrActions::actToggleTerminal->isChecked()); } void KRslots::insertFileName(bool fullPath) { QString filename = ACTIVE_VIEW->getCurrentItem(); if (filename.isEmpty()) { return; } if (fullPath) { const QString path = FileSystem::ensureTrailingSlash(ACTIVE_PANEL->virtualPath()) .toDisplayString(QUrl::PreferLocalFile); filename = path + filename; } filename = KrServices::quote(filename); if (MAIN_VIEW->cmdLine()->isVisible() || !MAIN_VIEW->terminalDock()->isTerminalVisible()) { QString current = MAIN_VIEW->cmdLine()->text(); if (current.length() != 0 && !current.endsWith(' ')) current += ' '; MAIN_VIEW->cmdLine()->setText(current + filename); MAIN_VIEW->cmdLine()->setFocus(); } else if (MAIN_VIEW->terminalDock()->isTerminalVisible()) { filename = ' ' + filename + ' '; MAIN_VIEW->terminalDock()->sendInput(filename, false); MAIN_VIEW->terminalDock()->setFocus(); } } void KRslots::refresh(const QUrl &u) { ACTIVE_FUNC->openUrl(u); } void KRslots::runKonfigurator(bool firstTime) { Konfigurator *konfigurator = new Konfigurator(firstTime); connect(konfigurator, SIGNAL(configChanged(bool)), SLOT(configChanged(bool))); //FIXME - no need to exec konfigurator->exec(); delete konfigurator; } void KRslots::configChanged(bool isGUIRestartNeeded) { krConfig->sync(); if (isGUIRestartNeeded) { krApp->setUpdatesEnabled(false); KConfigGroup group(krConfig, "Look&Feel"); FileItem::loadUserDefinedFolderIcons(group.readEntry("Load User Defined Folder Icons", _UserDefinedFolderIcons)); bool leftActive = ACTIVE_PANEL->gui->isLeft(); MAIN_VIEW->leftManager()->slotRecreatePanels(); MAIN_VIEW->rightManager()->slotRecreatePanels(); if(leftActive) LEFT_PANEL->slotFocusOnMe(); else RIGHT_PANEL->slotFocusOnMe(); MAIN_VIEW->fnKeys()->updateShortcuts(); KrSelectionMode::resetSelectionHandler(); krApp->setUpdatesEnabled(true); } krApp->setTray(); // really ugly, but reload the Fn keys just in case - csaba: any better idea? MAIN_VIEW->fnKeys()->updateShortcuts(); const bool showHidden = KConfigGroup(krConfig, "Look&Feel") .readEntry("Show Hidden", KrActions::actToggleHidden->isChecked()); if (showHidden != KrActions::actToggleHidden->isChecked()) { KrActions::actToggleHidden->setChecked(showHidden); MAIN_VIEW->leftManager()->refreshAllTabs(); MAIN_VIEW->rightManager()->refreshAllTabs(); } } void KRslots::showHiddenFiles(bool show) { KConfigGroup group(krConfig, "Look&Feel"); group.writeEntry("Show Hidden", show); MAIN_VIEW->leftManager()->refreshAllTabs(); MAIN_VIEW->rightManager()->refreshAllTabs(); } void KRslots::swapPanels() { QUrl leftURL = LEFT_PANEL->virtualPath(); QUrl rightURL = RIGHT_PANEL->virtualPath(); LEFT_PANEL->func->openUrl(rightURL); RIGHT_PANEL->func->openUrl(leftURL); } void KRslots::toggleSwapSides() { MAIN_VIEW->swapSides(); } void KRslots::search() { if (KrSearchDialog::SearchDialog != 0) { KConfigGroup group(krConfig, "Search"); if (group.readEntry("Window Maximized", false)) KrSearchDialog::SearchDialog->showMaximized(); else KrSearchDialog::SearchDialog->showNormal(); KrSearchDialog::SearchDialog->raise(); KrSearchDialog::SearchDialog->activateWindow(); } else KrSearchDialog::SearchDialog = new KrSearchDialog(); } void KRslots::locate() { if (!KrServices::cmdExist("locate")) { KMessageBox::error(krApp, i18n("Cannot find the 'locate' command. Please install the " "findutils-locate package of GNU, or set its dependencies in " "Konfigurator")); return; } if (LocateDlg::LocateDialog != 0) { LocateDlg::LocateDialog->showNormal(); LocateDlg::LocateDialog->raise(); LocateDlg::LocateDialog->activateWindow(); LocateDlg::LocateDialog->reset(); } else LocateDlg::LocateDialog = new LocateDlg(); } void KRslots::runTerminal(const QString & dir) { KProcess proc; proc.setWorkingDirectory(dir); KConfigGroup group(krConfig, "General"); QString term = group.readEntry("Terminal", _Terminal); QStringList sepdArgs = KShell::splitArgs(term, KShell::TildeExpand); if (sepdArgs.isEmpty()) { KMessageBox::error(krMainWindow, i18nc("Arg is a string containing the bad quoting.", "Bad quoting in terminal command:\n%1", term)); return; } for (int i = 0; i < sepdArgs.size(); i++) { if (sepdArgs[i] == "%d") { sepdArgs[i] = dir; } } proc << sepdArgs; if (!proc.startDetached()) KMessageBox::sorry(krApp, i18n("Error executing %1.", term)); } void KRslots::homeTerminal() { runTerminal(QDir::homePath()); } void KRslots::multiRename() { QStringList lst = KrServices::supportedTools(); int i = lst.indexOf("RENAME"); if (i == -1) { KMessageBox::sorry(krApp, i18n("Cannot find a batch rename tool.\nYou can get KRename at http://www.krename.net")); return; } QString pathToRename = lst[i+1]; const QStringList names = ACTIVE_PANEL->gui->getSelectedNames(); if (names.isEmpty()) { return; } KProcess proc; proc << pathToRename; for (const QString name: names) { FileItem *file = ACTIVE_FUNC->files()->getFileItem(name); if (!file) continue; const QUrl url = file->getUrl(); // KRename only supports the recursive option combined with a local directory path if (file->isDir() && url.scheme() == "file") { proc << "-r" << url.path(); } else { proc << url.toString(); } } if (!proc.startDetached()) KMessageBox::error(0, i18n("Error executing '%1'.", proc.program().join(" "))); } void KRslots::rootKrusader() { if (KMessageBox::warningContinueCancel( krApp, i18n("Improper operations in root mode can damage your operating system. " "

Furthermore, running UI applications as root is insecure and can " "allow attackers to gain root access."), QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "Confirm Root Mode", KMessageBox::Notify | KMessageBox::Dangerous) != KMessageBox::Continue) return; if (!KrServices::isExecutable(KDESU_PATH)) { KMessageBox::sorry(krApp, i18n("Cannot start root mode Krusader, %1 not found or not executable. " "Please verify that kde-cli-tools are installed.", QString(KDESU_PATH))); return; } KProcess proc; proc << KDESU_PATH << "-c" << QApplication::instance()->applicationFilePath() + " --left=" + KrServices::quote(LEFT_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)) + " --right=" + KrServices::quote(RIGHT_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)); if (!proc.startDetached()) KMessageBox::error(0, i18n("Error executing %1.", proc.program()[0])); } void KRslots::slotSplit() { const QStringList list = ACTIVE_PANEL->gui->getSelectedNames(); QString name; // first, see if we've got exactly 1 selected file, if not, try the current one if (list.count() == 1) name = list[0]; if (name.isEmpty()) { // if we got here, then one of the panel can't be sure what file to diff KMessageBox::error(0, i18n("Do not know which file to split.")); return; } QUrl fileURL = ACTIVE_FUNC->files()->getUrl(name); if (fileURL.isEmpty()) return; if (ACTIVE_FUNC->files()->getFileItem(name)->isDir()) { KMessageBox::sorry(krApp, i18n("You cannot split a folder.")); return ; } const QUrl destDir = ACTIVE_PANEL->otherPanel()->virtualPath(); SplitterGUI splitterGUI(MAIN_VIEW, fileURL, destDir); if (splitterGUI.exec() == QDialog::Accepted) { bool splitToOtherPanel = splitterGUI.getDestinationDir().matches(ACTIVE_PANEL->otherPanel()->virtualPath(), QUrl::StripTrailingSlash); Splitter split(MAIN_VIEW, fileURL, splitterGUI.getDestinationDir(), splitterGUI.overWriteFiles()); split.split(splitterGUI.getSplitSize()); if (splitToOtherPanel) ACTIVE_PANEL->otherPanel()->func->refresh(); } } void KRslots::slotCombine() { const QStringList list = ACTIVE_PANEL->gui->getSelectedNames(); if (list.isEmpty()) { KMessageBox::error(0, i18n("Do not know which files to combine.")); return; } QUrl baseURL; bool unixStyle = false; bool windowsStyle = false; QString commonName; int commonLength = 0; /* checking splitter names */ for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) { QUrl url = ACTIVE_FUNC->files()->getUrl(*it); if (url.isEmpty()) return; if (ACTIVE_FUNC->files()->getFileItem(*it)->isDir()) { KMessageBox::sorry(krApp, i18n("You cannot combine a folder.")); return ; } if (!unixStyle) { QString name = url.fileName(); int extPos = name.lastIndexOf('.'); QString ext = name.mid(extPos + 1); name.truncate(extPos); url = url.adjusted(QUrl::RemoveFilename); url.setPath(url.path() + name); bool isExtInt; ext.toInt(&isExtInt, 10); if (extPos < 1 || ext.isEmpty() || (ext != "crc" && !isExtInt)) { if (windowsStyle) { KMessageBox::error(0, i18n("Not a split file: %1.", url.toDisplayString(QUrl::PreferLocalFile))); return; } unixStyle = true; } else { if (ext != "crc") windowsStyle = true; if (baseURL.isEmpty()) baseURL = url; else if (baseURL != url) { KMessageBox::error(0, i18n("Select only one split file.")); return; } } } if (unixStyle) { bool error = true; do { QString shortName = *it; QChar lastChar = shortName.at(shortName.length() - 1); if (lastChar.isLetter()) { char fillLetter = (lastChar.toUpper() == lastChar) ? 'A' : 'a'; if (commonName.isNull()) { commonLength = shortName.length(); commonName = shortName; while (commonName.length()) { QString shorter = commonName.left(commonName.length() - 1); QString testFile = shorter.leftJustified(commonLength, fillLetter); if (ACTIVE_FUNC->files()->getFileItem(testFile) == 0) break; else { commonName = shorter; baseURL = ACTIVE_PANEL->virtualPath().adjusted(QUrl::StripTrailingSlash); baseURL.setPath(baseURL.path() + '/' + (testFile)); } } error = (commonName == shortName); } else if (commonLength == shortName.length() && shortName.startsWith(commonName)) error = false; } } while (false); if (error) { KMessageBox::error(0, i18n("Not a split file: %1.", url.toDisplayString(QUrl::PreferLocalFile))); return; } } } // ask the user for the copy dest QUrl dest = KChooseDir::getDir(i18n("Combining %1.* to folder:", baseURL.toDisplayString(QUrl::PreferLocalFile)), ACTIVE_PANEL->otherPanel()->virtualPath(), ACTIVE_PANEL->virtualPath()); if (dest.isEmpty()) return ; // the user canceled bool combineToOtherPanel = (dest.matches(ACTIVE_PANEL->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)); Combiner combine(MAIN_VIEW, baseURL, dest, unixStyle); combine.combine(); if (combineToOtherPanel) ACTIVE_PANEL->otherPanel()->func->refresh(); } void KRslots::manageUseractions() { ActionMan actionMan(MAIN_VIEW); } #ifdef SYNCHRONIZER_ENABLED void KRslots::slotSynchronizeDirs(QStringList selected) { new SynchronizerGUI(0, LEFT_PANEL->virtualPath(), RIGHT_PANEL->virtualPath(), selected); } #endif void KRslots::compareSetup() { for (int i = 0; KrActions::compareArray[i] != 0; i++) if ((*KrActions::compareArray[i])->isChecked()) { KConfigGroup group(krConfig, "Private"); group.writeEntry("Compare Mode", i); break; } } /** called by actions actExec* to choose the built-in command line mode */ void KRslots::execTypeSetup() { for (int i = 0; KrActions::execTypeArray[i] != 0; i++) if ((*KrActions::execTypeArray[i])->isChecked()) { if (*KrActions::execTypeArray[i] == KrActions::actExecTerminalEmbedded) { // if commands are to be executed in the TE, it must be loaded MAIN_VIEW->terminalDock()->initialise(); } KConfigGroup grp(krConfig, "Private"); grp.writeEntry("Command Execution Mode", i); break; } } void KRslots::slotDiskUsage() { DiskUsageGUI du(ACTIVE_PANEL->virtualPath(), MAIN_VIEW); } void KRslots::applicationStateChanged() { if (MAIN_VIEW == 0) { /* CRASH FIX: it's possible that the method is called after destroying the main view */ return; } if(qApp->applicationState() == Qt::ApplicationActive || qApp->applicationState() == Qt::ApplicationInactive) { LEFT_PANEL->panelVisible(); RIGHT_PANEL->panelVisible(); } else { LEFT_PANEL->panelHidden(); RIGHT_PANEL->panelHidden(); } } void KRslots::emptyTrash() { KrTrashHandler::emptyTrash(); } #define OPEN_ID 100001 #define EMPTY_TRASH_ID 100002 void KRslots::trashPopupMenu() { QMenu trashMenu(krApp); QAction * act = trashMenu.addAction(krLoader->loadIcon("document-open", KIconLoader::Panel), i18n("Open trash bin")); act->setData(QVariant(OPEN_ID)); act = trashMenu.addAction(krLoader->loadIcon("trash-empty", KIconLoader::Panel), i18n("Empty trash bin")); act->setData(QVariant(EMPTY_TRASH_ID)); int result = -1; QAction *res = trashMenu.exec(QCursor::pos()); if (res && res->data().canConvert ()) result = res->data().toInt(); if (result == OPEN_ID) { ACTIVE_FUNC->openUrl(QUrl(QStringLiteral("trash:/"))); } else if (result == EMPTY_TRASH_ID) { KrTrashHandler::emptyTrash(); } } //shows the JavaScript-Console void KRslots::jsConsole() { #ifdef __KJSEMBED__ if (! krJS) krJS = new KrJS(); krJS->view()->show(); #endif } void KRslots::addBookmark() { krBookMan->bookmarkCurrent(ACTIVE_PANEL->virtualPath()); } void KRslots::cmdlinePopup() { MAIN_VIEW->cmdLine()->popup(); } diff --git a/krusader/krusader.cpp b/krusader/krusader.cpp index 3e572ab4..71297c7b 100644 --- a/krusader/krusader.cpp +++ b/krusader/krusader.cpp @@ -1,653 +1,653 @@ /*************************************************************************** krusader.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krusader.h" // QtCore #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include // QtDBus #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "krusaderversion.h" -#include "kicons.h" -#include "krusaderview.h" #include "defaults.h" -#include "krslots.h" +#include "kicons.h" +#include "kractions.h" +#include "krglobal.h" #include "krservices.h" -// This makes gcc-4.1 happy. Warning about possible problem with KrAction's dtor not called +#include "krslots.h" #include "krtrashhandler.h" -#include "tabactions.h" -#include "krglobal.h" -#include "kractions.h" +#include "krusaderversion.h" +#include "krusaderview.h" #include "panelmanager.h" -#include "Panel/krcolorcache.h" -#include "Panel/viewactions.h" -#include "Panel/listpanelactions.h" -#include "Panel/krpanel.h" -#include "Panel/krview.h" -#include "Panel/krviewfactory.h" -#include "UserAction/kraction.h" -#include "UserAction/expander.h" -#include "UserAction/useraction.h" -#include "Dialogs/popularurls.h" +#include "tabactions.h" + +#include "BookMan/krbookmarkhandler.h" #include "Dialogs/checksumdlg.h" #include "Dialogs/krpleasewait.h" -#include "GUI/krremoteencodingmenu.h" -#include "GUI/kfnkeys.h" -#include "GUI/kcmdline.h" -#include "GUI/terminaldock.h" -#include "GUI/krusaderstatus.h" +#include "Dialogs/popularurls.h" #include "FileSystem/fileitem.h" #include "FileSystem/krpermhandler.h" -#include "MountMan/kmountman.h" -#include "Konfigurator/kgprotocols.h" -#include "BookMan/krbookmarkhandler.h" -#include "KViewer/krviewer.h" +#include "GUI/kcmdline.h" +#include "GUI/kfnkeys.h" +#include "GUI/krremoteencodingmenu.h" +#include "GUI/krusaderstatus.h" +#include "GUI/terminaldock.h" #include "JobMan/jobman.h" - +#include "KViewer/krviewer.h" +#include "Konfigurator/kgprotocols.h" +#include "MountMan/kmountman.h" +#include "Panel/PanelView/krview.h" +#include "Panel/PanelView/krviewfactory.h" +#include "Panel/krcolorcache.h" +#include "Panel/krpanel.h" +#include "Panel/listpanelactions.h" +#include "Panel/viewactions.h" +#include "UserAction/expander.h" +// This makes gcc-4.1 happy. Warning about possible problem with KrAction's dtor not called +#include "UserAction/kraction.h" +#include "UserAction/useraction.h" #ifdef __KJSEMBED__ #include "KrJS/krjs.h" #endif // define the static members Krusader *Krusader::App = 0; QString Krusader::AppName; // KrBookmarkHandler *Krusader::bookman = 0; //QTextOStream *Krusader::_krOut = QTextOStream(::stdout); #ifdef __KJSEMBED__ KrJS *Krusader::js = 0; QAction *Krusader::actShowJSConsole = 0; #endif // construct the views, statusbar and menu bars and prepare Krusader to start Krusader::Krusader(const QCommandLineParser &parser) : KParts::MainWindow(0, Qt::Window | Qt::WindowTitleHint | Qt::WindowContextHelpButtonHint), _listPanelActions(0), isStarting(true), isExiting(false), _quit(false) { // create the "krusader" App = this; krMainWindow = this; SLOTS = new KRslots(this); setXMLFile("krusaderui.rc"); // kpart-related xml file plzWait = new KRPleaseWaitHandler(this); const bool runKonfig = versionControl(); QString message; switch (krConfig->accessMode()) { case KConfigBase::NoAccess : message = "Krusader's configuration file can't be found. Default values will be used."; break; case KConfigBase::ReadOnly : message = "Krusader's configuration file is in READ ONLY mode (why is that!?) Changed values will not be saved"; break; case KConfigBase::ReadWrite : message = ""; break; } if (!message.isEmpty()) { KMessageBox::error(krApp, message); } // create an icon loader krLoader = KIconLoader::global(); // iconLoader->addExtraDesktopThemes(); // create MountMan KrGlobal::mountMan = new KMountMan(this); connect(KrGlobal::mountMan, SIGNAL(refreshPanel(QUrl)), SLOTS, SLOT(refresh(QUrl))); // create bookman krBookMan = new KrBookmarkHandler(this); // create job manager krJobMan = new JobMan(this); _popularUrls = new PopularUrls(this); // create the main view MAIN_VIEW = new KrusaderView(this); // setup all the krusader's actions setupActions(); // init the permmision handler class KRpermHandler::init(); // init the protocol handler KgProtocols::init(); const KConfigGroup lookFeelGroup(krConfig, "Look&Feel"); FileItem::loadUserDefinedFolderIcons(lookFeelGroup.readEntry("Load User Defined Folder Icons", _UserDefinedFolderIcons)); const KConfigGroup startupGroup(krConfig, "Startup"); QString startProfile = startupGroup.readEntry("Starter Profile Name", QString()); QList leftTabs; QList rightTabs; // get command-line arguments if (parser.isSet("left")) { leftTabs = KrServices::toUrlList(parser.value("left").split(',')); startProfile.clear(); } if (parser.isSet("right")) { rightTabs = KrServices::toUrlList(parser.value("right").split(',')); startProfile.clear(); } if (parser.isSet("profile")) startProfile = parser.value("profile"); if (!startProfile.isEmpty()) { leftTabs.clear(); rightTabs.clear(); } // starting the panels MAIN_VIEW->start(startupGroup, startProfile.isEmpty(), leftTabs, rightTabs); // create a status bar KrusaderStatus *status = new KrusaderStatus(this); setStatusBar(status); status->setWhatsThis(i18n("Statusbar will show basic information " "about file below mouse pointer.")); // create tray icon (if needed) const bool startToTray = startupGroup.readEntry("Start To Tray", _StartToTray); setTray(startToTray); setCentralWidget(MAIN_VIEW); // manage our keyboard short-cuts //KAcceleratorManager::manage(this,true); setCursor(Qt::ArrowCursor); if (! startProfile.isEmpty()) MAIN_VIEW->profiles(startProfile); // restore gui settings { // now, check if we need to create a konsole_part // call the XML GUI function to draw the UI createGUI(MAIN_VIEW->terminalDock()->part()); // this needs to be called AFTER createGUI() !!! updateUserActions(); _listPanelActions->guiUpdated(); // not using this. See savePosition() //applyMainWindowSettings(); const KConfigGroup cfgToolbar(krConfig, "Main Toolbar"); toolBar()->applySettings(cfgToolbar); const KConfigGroup cfgJobBar(krConfig, "Job Toolbar"); toolBar("jobToolBar")->applySettings(cfgJobBar); const KConfigGroup cfgActionsBar(krConfig, "Actions Toolbar"); toolBar("actionsToolBar")->applySettings(cfgActionsBar); // restore toolbars position and visibility restoreState(startupGroup.readEntry("State", QByteArray())); statusBar()->setVisible(startupGroup.readEntry("Show status bar", _ShowStatusBar)); MAIN_VIEW->updateGUI(startupGroup); // popular urls _popularUrls->load(); } if (runKonfig) SLOTS->runKonfigurator(true); KConfigGroup viewerModuleGrp(krConfig, "ViewerModule"); if (viewerModuleGrp.readEntry("FirstRun", true)) { KrViewer::configureDeps(); viewerModuleGrp.writeEntry("FirstRun", false); } if (!runKonfig) { KConfigGroup cfg(krConfig, "Private"); move(cfg.readEntry("Start Position", _StartPosition)); resize(cfg.readEntry("Start Size", _StartSize)); } // view initialized; show window or only tray if (!startToTray) { show(); } KrTrashHandler::startWatcher(); isStarting = false; //HACK - used by [ListerTextArea|KrSearchDialog|LocateDlg]:keyPressEvent() KrGlobal::copyShortcut = _listPanelActions->actCopy->shortcut(); //HACK: make sure the active view becomes focused // for some reason sometimes the active view cannot be focused immediately at this point, // so queue it for the main loop QTimer::singleShot(0, ACTIVE_PANEL->view->widget(), SLOT(setFocus())); _openUrlTimer.setSingleShot(true); connect(&_openUrlTimer, SIGNAL(timeout()), SLOT(doOpenUrl())); KStartupInfo *startupInfo = new KStartupInfo(0, this); connect(startupInfo, &KStartupInfo::gotNewStartup, this, &Krusader::slotGotNewStartup); connect(startupInfo, &KStartupInfo::gotRemoveStartup, this, &Krusader::slotGotRemoveStartup); } Krusader::~Krusader() { KrTrashHandler::stopWatcher(); if (!isExiting) // save the settings if it was not saved (SIGTERM received) saveSettings(); delete MAIN_VIEW; MAIN_VIEW = 0; App = 0; } void Krusader::setTray(bool forceCreation) { const bool trayIsNeeded = forceCreation || KConfigGroup(krConfig, "Look&Feel") .readEntry("Minimize To Tray", _ShowTrayIcon); if (!sysTray && trayIsNeeded) { sysTray = new KStatusNotifierItem(this); sysTray->setIconByName(privIcon()); // we have our own "quit" method, re-connect QAction *quitAction = sysTray->action(QStringLiteral("quit")); if (quitAction) { disconnect(quitAction, &QAction::triggered, nullptr, nullptr); connect(quitAction, &QAction::triggered, this, &Krusader::quit); } } else if (sysTray && !trayIsNeeded) { // user does not want tray anymore :( sysTray->deleteLater(); } } bool Krusader::versionControl() { // create config file krConfig = KSharedConfig::openConfig().data(); KConfigGroup nogroup(krConfig, QString()); const bool firstRun = nogroup.readEntry("First Time", true); KrGlobal::sCurrentConfigVersion = nogroup.readEntry("Config Version", -1); // first installation of krusader if (firstRun) { KMessageBox::information( krApp, i18n("Welcome to Krusader.

As this is your first run, your machine " "will now be checked for external applications. Then the Konfigurator will " "be launched where you can customize Krusader to your needs.

")); } nogroup.writeEntry("Version", VERSION); nogroup.writeEntry("First Time", false); krConfig->sync(); QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/krusader/")); return firstRun; } void Krusader::statusBarUpdate(const QString& mess) { // change the message on the statusbar for 5 seconds if (statusBar()->isVisible()) statusBar()->showMessage(mess, 5000); } bool Krusader::event(QEvent *e) { if(e->type() == QEvent::ApplicationPaletteChange) { KrColorCache::getColorCache().refreshColors(); } return KParts::MainWindow::event(e); } // Moving from Pixmap actions to generic filenames - thanks to Carsten Pfeiffer void Krusader::setupActions() { QAction *bringToTopAct = new QAction(i18n("Bring Main Window to Top"), this); actionCollection()->addAction("bring_main_window_to_top", bringToTopAct); connect(bringToTopAct, SIGNAL(triggered()), SLOT(moveToTop())); KrActions::setupActions(this); _krActions = new KrActions(this); _viewActions = new ViewActions(this, this); _listPanelActions = new ListPanelActions(this, this); _tabActions = new TabActions(this, this); } /////////////////////////////////////////////////////////////////////////// //////////////////// implementation of slots ////////////////////////////// /////////////////////////////////////////////////////////////////////////// void Krusader::savePosition() { KConfigGroup cfg(krConfig, "Private"); cfg.writeEntry("Start Position", pos()); cfg.writeEntry("Start Size", size()); cfg = krConfig->group("Startup"); MAIN_VIEW->saveSettings(cfg); // NOTE: this would save current window state/size, statusbar and settings for each toolbar. // We are not using this and saving everything manually because // - it does not save window position // - window size save/restore does sometimes not work (multi-monitor setup) // - saving the statusbar visibility should be independent from window position and restoring it // does not work properly. //KConfigGroup cfg = KConfigGroup(&cfg, "MainWindowSettings"); //saveMainWindowSettings(cfg); //statusBar()->setVisible(cfg.readEntry("StatusBar", "Enabled") != "Disabled"); krConfig->sync(); } void Krusader::saveSettings() { // workaround: revert terminal fullscreen mode before saving widget and toolbar visibility if (MAIN_VIEW->isTerminalEmulatorFullscreen()) { MAIN_VIEW->setTerminalEmulator(false, true); } KConfigGroup noGroup(krConfig, QString()); noGroup.writeEntry("Config Version", KrGlobal::sConfigVersion); // save toolbar settings KConfigGroup cfg(krConfig, "Main Toolbar"); toolBar()->saveSettings(cfg); cfg = krConfig->group("Job Toolbar"); toolBar("jobToolBar")->saveSettings(cfg); cfg = krConfig->group("Actions Toolbar"); toolBar("actionsToolBar")->saveSettings(cfg); cfg = krConfig->group("Startup"); // save toolbar visibility and position cfg.writeEntry("State", saveState()); cfg.writeEntry("Show status bar", statusBar()->isVisible()); // save panel and window settings if (cfg.readEntry("Remember Position", _RememberPos)) savePosition(); // save the gui components visibility if (cfg.readEntry("UI Save Settings", _UiSave)) { cfg.writeEntry("Show FN Keys", KrActions::actToggleFnkeys->isChecked()); cfg.writeEntry("Show Cmd Line", KrActions::actToggleCmdline->isChecked()); cfg.writeEntry("Show Terminal Emulator", KrActions::actToggleTerminal->isChecked()); } // save popular links _popularUrls->save(); krConfig->sync(); } void Krusader::closeEvent(QCloseEvent *event) { if (!sysTray || _quit) { _quit = false; // in case quit will be aborted KParts::MainWindow::closeEvent(event); // (may) quit, continues with queryClose()... } else { // close window to tray event->ignore(); hide(); } } void Krusader::showEvent(QShowEvent *event) { const KConfigGroup lookFeelGroup(krConfig, "Look&Feel"); if (sysTray && !lookFeelGroup.readEntry("Minimize To Tray", _ShowTrayIcon)) { // restoring from "start to tray", tray icon is not needed anymore sysTray->deleteLater(); } KParts::MainWindow::showEvent(event); } bool Krusader::queryClose() { if (isStarting || isExiting) return false; if (qApp->isSavingSession()) { // KDE is logging out, accept the close acceptClose(); return true; } const KConfigGroup cfg = krConfig->group("Look&Feel"); const bool confirmExit = cfg.readEntry("Warn On Exit", _WarnOnExit); // ask user and wait until all KIO::job operations are terminated. Krusader won't exit before // that anyway if (!krJobMan->waitForJobs(confirmExit)) return false; /* First try to close the child windows, because it's the safer way to avoid crashes, then close the main window. If closing a child is not successful, then we cannot let the main window close. */ for (;;) { QWidgetList list = QApplication::topLevelWidgets(); QWidget *activeModal = QApplication::activeModalWidget(); QWidget *w = list.at(0); if (activeModal && activeModal != this && activeModal != menuBar() && list.contains(activeModal) && !activeModal->isHidden()) { w = activeModal; } else { int i = 1; for (; i < list.count(); ++i) { w = list.at(i); if (!(w && (w == this || w->isHidden() || w == menuBar()))) break; } if (i == list.count()) w = 0; } if (!w) break; if (!w->close()) { if (w->inherits("QDialog")) { fprintf(stderr, "Failed to close: %s\n", w->metaObject()->className()); } return false; } } acceptClose(); return true; } void Krusader::acceptClose() { saveSettings(); emit shutdown(); // Removes the DBUS registration of the application. Single instance mode requires unique appid. // As Krusader is exiting, we release that unique appid, so new Krusader instances // can be started. QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.unregisterObject("/Instances/" + Krusader::AppName); isExiting = true; } // the please wait dialog functions void Krusader::startWaiting(QString msg, int count , bool cancel) { plzWait->startWaiting(msg , count, cancel); } bool Krusader::wasWaitingCancelled() const { return plzWait->wasCancelled(); } void Krusader::stopWait() { plzWait->stopWait(); } void Krusader::updateUserActions() { KActionMenu *userActionMenu = (KActionMenu *) KrActions::actUserMenu; if (userActionMenu) { userActionMenu->menu()->clear(); userActionMenu->addAction(KrActions::actManageUseractions); userActionMenu->addSeparator(); krUserAction->populateMenu(userActionMenu, NULL); } } const char* Krusader::privIcon() { if (geteuid()) return "krusader_user"; else return "krusader_root"; } void Krusader::quit() { _quit = true; // remember that we want to quit and not close to tray close(); // continues with closeEvent()... } void Krusader::moveToTop() { if (isHidden()) show(); KWindowSystem::forceActiveWindow(winId()); } bool Krusader::isRunning() { moveToTop(); //FIXME - doesn't belong here return true; } bool Krusader::isLeftActive() { return MAIN_VIEW->isLeftActive(); } bool Krusader::openUrl(QString url) { _urlToOpen = url; _openUrlTimer.start(0); return true; } void Krusader::doOpenUrl() { QUrl url = QUrl::fromUserInput(_urlToOpen, QDir::currentPath(), QUrl::AssumeLocalFile); _urlToOpen.clear(); int tab = ACTIVE_MNG->findTab(url); if(tab >= 0) ACTIVE_MNG->setActiveTab(tab); else if((tab = OTHER_MNG->findTab(url)) >= 0) { OTHER_MNG->setActiveTab(tab); OTHER_MNG->currentPanel()->view->widget()->setFocus(); } else ACTIVE_MNG->slotNewTab(url); } void Krusader::slotGotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data) { Q_UNUSED(id) Q_UNUSED(data) // This is here to show busy mouse cursor when _other_ applications are launched, not for krusader itself. qApp->setOverrideCursor(Qt::BusyCursor); } void Krusader::slotGotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data) { Q_UNUSED(id) Q_UNUSED(data) qApp->restoreOverrideCursor(); } KrView *Krusader::activeView() { return ACTIVE_PANEL->view; } AbstractPanelManager *Krusader::activeManager() { return MAIN_VIEW->activeManager(); } AbstractPanelManager *Krusader::leftManager() { return MAIN_VIEW->leftManager(); } AbstractPanelManager *Krusader::rightManager() { return MAIN_VIEW->rightManager(); } diff --git a/krusader/krusaderview.cpp b/krusader/krusaderview.cpp index a67f1128..a28e7506 100644 --- a/krusader/krusaderview.cpp +++ b/krusader/krusaderview.cpp @@ -1,530 +1,529 @@ /*************************************************************************** krusaderview.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krusaderview.h" // QtCore #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include "krusader.h" #include "kractions.h" #include "krslots.h" #include "defaults.h" #include "Panel/listpanel.h" #include "Panel/panelfunc.h" #include "GUI/kcmdline.h" #include "GUI/kfnkeys.h" #include "GUI/terminaldock.h" #include "panelmanager.h" #include "GUI/profilemanager.h" #include "Dialogs/percentalsplitter.h" #include "krservices.h" -#include "Panel/krviewfactory.h" KrusaderView::KrusaderView(QWidget *parent) : QWidget(parent), activeMng(0) { } void KrusaderView::start(const KConfigGroup &cfg, bool restoreSettings, const QList &leftTabs, const QList &rightTabs) { //////////////////////////////// // make a 1x1 mainLayout, it will auto-expand: mainLayout = new QGridLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); // vertical splitter vert_splitter = new QSplitter(this); // splits between panels and terminal/cmdline vert_splitter->setOrientation(Qt::Vertical); // horizontal splitter horiz_splitter = new PercentalSplitter(vert_splitter); (_terminalDock = new TerminalDock(vert_splitter, krApp))->hide(); // create it hidden // create a command line thing _cmdLine = new KCMDLine(this); // add a panel manager for each side of the splitter leftMng = createManager(true); rightMng = createManager(false); leftMng->setOtherManager(rightMng); rightMng->setOtherManager(leftMng); // make the left panel focused at program start activeMng = leftMng; // create the function keys widget _fnKeys = new KFnKeys(this, krApp); _fnKeys->hide(); _fnKeys->setWhatsThis(i18n("Function keys allow performing fast " "operations on files.")); // and insert the whole thing into the main layout... at last mainLayout->addWidget(vert_splitter, 0, 0); //<> mainLayout->addWidget(_cmdLine, 1, 0); mainLayout->addWidget(_fnKeys, 2, 0); mainLayout->activate(); // get the last saved sizes of the splitter QList lst = cfg.readEntry("Splitter Sizes", QList()); if (lst.count() != 2) { lst.clear(); lst.push_back(100); lst.push_back(100); } else if (lst[0] < 1 && lst[1] < 1) { lst[ 0 ] = 100; lst[ 1 ] = 100; } horiz_splitter->setSizes(lst); verticalSplitterSizes = cfg.readEntry("Terminal Emulator Splitter Sizes", QList ()); if (verticalSplitterSizes.count() != 2 || (verticalSplitterSizes[0] < 1 && verticalSplitterSizes[1] < 1)) { verticalSplitterSizes.clear(); verticalSplitterSizes << 100 << 100; } leftPanel()->start(leftTabs.isEmpty() ? QUrl::fromLocalFile(QDir::homePath()) : leftTabs.at(0)); rightPanel()->start(rightTabs.isEmpty() ? QUrl::fromLocalFile(QDir::homePath()) : rightTabs.at(0)); ACTIVE_PANEL->gui->slotFocusOnMe(); // left starts out active for (int i = 1; i < leftTabs.count(); i++) leftMng->slotNewTab(leftTabs.at(i), false); for (int j = 1; j < rightTabs.count(); j++) rightMng->slotNewTab(rightTabs.at(j), false); // this is needed so that all tab labels get updated leftMng->layoutTabs(); rightMng->layoutTabs(); if(restoreSettings) { if(leftTabs.isEmpty()) leftMng->loadSettings(KConfigGroup(&cfg, "Left Tab Bar")); if(rightTabs.isEmpty()) rightMng->loadSettings(KConfigGroup(&cfg, "Right Tab Bar")); if (cfg.readEntry("Left Side Is Active", false)) leftPanel()->slotFocusOnMe(); else rightPanel()->slotFocusOnMe(); } } void KrusaderView::updateGUI(const KConfigGroup &cfg) { if (!cfg.readEntry("Show Cmd Line", _ShowCmdline)) { cmdLine()->hide(); KrActions::actToggleCmdline->setChecked(false); } else { cmdLine()->show(); KrActions::actToggleCmdline->setChecked(true); } // update the Fn bar to the shortcuts selected by the user fnKeys()->updateShortcuts(); if (!cfg.readEntry("Show FN Keys", _ShowFNkeys)) { fnKeys()->hide(); KrActions::actToggleFnkeys->setChecked(false); } else { fnKeys()->show(); KrActions::actToggleFnkeys->setChecked(true); } // set vertical mode if (cfg.readEntry("Vertical Mode", false)) { toggleVerticalMode(); } if (cfg.readEntry("Show Terminal Emulator", _ShowTerminalEmulator)) { setTerminalEmulator(true); // create konsole_part }; } void KrusaderView::setPanelSize(bool leftPanel, int percent) { QList panelSizes = horiz_splitter->sizes(); int totalSize = panelSizes[0] + panelSizes[1]; if (leftPanel) { panelSizes[0] = totalSize * percent / 100; panelSizes[1] = totalSize * (100 - percent) / 100; } else { // == RIGHT_PANEL panelSizes[0] = totalSize * (100 - percent) / 100; panelSizes[1] = totalSize * percent / 100; } horiz_splitter->setSizes(panelSizes); } PanelManager *KrusaderView::createManager(bool left) { PanelManager *p = new PanelManager(horiz_splitter, krApp, left); connect(p, SIGNAL(draggingTab(PanelManager*,QMouseEvent*)), SLOT(draggingTab(PanelManager*,QMouseEvent*))); connect(p, SIGNAL(draggingTabFinished(PanelManager*,QMouseEvent*)), SLOT(draggingTabFinished(PanelManager*,QMouseEvent*))); connect(p, SIGNAL(pathChanged(ListPanel*)), SLOT(slotPathChanged(ListPanel*))); connect(p, SIGNAL(setActiveManager(PanelManager*)), SLOT(slotSetActiveManager(PanelManager*))); return p; } ListPanel* KrusaderView::leftPanel() { return leftMng->currentPanel()->gui; } ListPanel* KrusaderView::rightPanel() { return rightMng->currentPanel()->gui; } // updates the command line whenever current panel or its path changes ////////////////////////////////////////////////////////// void KrusaderView::slotPathChanged(ListPanel *p) { if(p == ACTIVE_PANEL) { _cmdLine->setCurrent(p->lastLocalPath()); KConfigGroup cfg = krConfig->group("General"); if (cfg.readEntry("Send CDs", _SendCDs)) { // hopefully, this is cached in kconfig _terminalDock->sendCd(p->lastLocalPath()); } } } int KrusaderView::getFocusCandidates(QVector &widgets) { ACTIVE_PANEL->gui->getFocusCandidates(widgets); if(_terminalDock->isTerminalVisible()) widgets << _terminalDock; if(_cmdLine->isVisible()) widgets << _cmdLine; for(int i = 0; i < widgets.count(); i++) { if(widgets[i] == focusWidget() || widgets[i]->focusWidget() == focusWidget()) return i; } return -1; } void KrusaderView::focusUp() { QVector widgets; int currentFocus = getFocusCandidates(widgets); if(currentFocus < 0) return; currentFocus--; if(currentFocus >= 0 && currentFocus < widgets.count()) widgets[currentFocus]->setFocus(); } void KrusaderView::focusDown() { QVector widgets; int currentFocus = getFocusCandidates(widgets); if(currentFocus < 0) return; currentFocus++; if(currentFocus < widgets.count()) widgets[currentFocus]->setFocus(); } void KrusaderView::cmdLineFocus() // command line receive's keyboard focus { _cmdLine->setFocus(); } void KrusaderView::cmdLineUnFocus() // return focus to the active panel { ACTIVE_PANEL->gui->slotFocusOnMe(); } // Tab - switch focus void KrusaderView::panelSwitch() { ACTIVE_PANEL->otherPanel()->gui->slotFocusOnMe(); } void KrusaderView::slotSetActiveManager(PanelManager *manager) { activeMng = manager; slotPathChanged(manager->currentPanel()->gui); } void KrusaderView::swapSides() { QList lst = horiz_splitter->sizes(); horiz_splitter->addWidget(leftMng); int old = lst[ 0 ]; lst[ 0 ] = lst [ 1 ]; lst[ 1 ] = old; horiz_splitter->setSizes(lst); PanelManager *tmpMng = leftMng; leftMng = rightMng; rightMng = tmpMng; leftMng->setLeft(true); rightMng->setLeft(false); leftPanel()->updateGeometry(); rightPanel()->updateGeometry(); } void KrusaderView::setTerminalEmulator(bool show, bool fullscreen) { static bool fnKeysShown = true; // first time init. should be overridden static bool cmdLineShown = true; static bool statusBarShown = true; static bool mainToolBarShown = true; static bool jobToolBarShown = true; static bool actionToolBarShown = true; static bool menuBarShown = true; static bool terminalEmulatorShown = true; if (show) { if (fullscreen) { // save what is shown fnKeysShown = !_fnKeys->isHidden(); cmdLineShown = !_cmdLine->isHidden(); statusBarShown = !krApp->statusBar()->isHidden(); mainToolBarShown = !krApp->toolBar()->isHidden(); jobToolBarShown = !krApp->toolBar("jobToolBar")->isHidden(); actionToolBarShown = !krApp->toolBar("actionToolBar")->isHidden(); menuBarShown = !krApp->menuBar()->isHidden(); terminalEmulatorShown = _terminalDock->isTerminalVisible(); } if(!_terminalDock->isTerminalVisible()) { // show terminal const bool isInitialized = _terminalDock->initialise(); if (!isInitialized) { _terminalDock->hide(); KrActions::actToggleTerminal->setChecked(false); return; } _terminalDock->show(); _terminalDock->setFocus(); slotPathChanged(ACTIVE_PANEL->gui); KrActions::actToggleTerminal->setChecked(true); } else if (fullscreen) { // save current terminal size before going to fullscreen verticalSplitterSizes = vert_splitter->sizes(); } if (fullscreen) { // hide everything else leftMng->hide(); rightMng->hide(); _fnKeys->hide(); _cmdLine->hide(); krApp->statusBar()->hide(); krApp->toolBar()->hide(); krApp->toolBar("jobToolBar")->hide(); krApp->toolBar("actionToolBar")->hide(); krApp->menuBar()->hide(); // fix showing nothing if terminal is open but splitter widget size is zero vert_splitter->setSizes(QList() << 0 << vert_splitter->height()); } else { vert_splitter->setSizes(verticalSplitterSizes); } } else { // hide const bool isFullscreen = isTerminalEmulatorFullscreen(); if (!(fullscreen && terminalEmulatorShown)) { // hide terminal emulator ACTIVE_PANEL->gui->slotFocusOnMe(); if (_terminalDock->isTerminalVisible() && !isFullscreen) verticalSplitterSizes = vert_splitter->sizes(); _terminalDock->hide(); KrActions::actToggleTerminal->setChecked(false); } else { // not fullscreen anymore but terminal is still visible vert_splitter->setSizes(verticalSplitterSizes); } if (isFullscreen) { // restore: unhide everything that was hidden before leftMng->show(); rightMng->show(); if (fnKeysShown) _fnKeys->show(); if (cmdLineShown) _cmdLine->show(); if (statusBarShown) krApp->statusBar()->show(); if (mainToolBarShown) krApp->toolBar()->show(); if (jobToolBarShown) krApp->toolBar("jobToolBar")->show(); if (actionToolBarShown) krApp->toolBar("actionToolBar")->show(); if (menuBarShown) krApp->menuBar()->show(); } } } void KrusaderView::focusTerminalEmulator() { if (_terminalDock->isTerminalVisible()) _terminalDock->setFocus(); } void KrusaderView::toggleFullScreenTerminalEmulator() { setTerminalEmulator(!isTerminalEmulatorFullscreen(), true); } bool KrusaderView::isTerminalEmulatorFullscreen() { return leftMng->isHidden() && rightMng->isHidden(); } void KrusaderView::profiles(QString profileName) { ProfileManager profileManager("Panel", this); profileManager.hide(); connect(&profileManager, SIGNAL(saveToProfile(QString)), this, SLOT(savePanelProfiles(QString))); connect(&profileManager, SIGNAL(loadFromProfile(QString)), this, SLOT(loadPanelProfiles(QString))); if (profileName.isEmpty()) profileManager.profilePopup(); else profileManager.loadProfile(profileName); } void KrusaderView::loadPanelProfiles(QString group) { KConfigGroup ldg(krConfig, group); leftMng->loadSettings(KConfigGroup(&ldg, "Left Tabs")); rightMng->loadSettings(KConfigGroup(&ldg, "Right Tabs")); if (ldg.readEntry("Left Side Is Active", true)) leftPanel()->slotFocusOnMe(); else rightPanel()->slotFocusOnMe(); } void KrusaderView::savePanelProfiles(QString group) { KConfigGroup svr(krConfig, group); svr.writeEntry("Vertical Mode", isVertical()); svr.writeEntry("Left Side Is Active", ACTIVE_PANEL->gui->isLeft()); leftMng->saveSettings(KConfigGroup(&svr, "Left Tabs"), false); rightMng->saveSettings(KConfigGroup(&svr, "Right Tabs"), false); } void KrusaderView::toggleVerticalMode() { if (horiz_splitter->orientation() == Qt::Vertical) { horiz_splitter->setOrientation(Qt::Horizontal); KrActions::actVerticalMode->setText(i18n("Vertical Mode")); KrActions::actVerticalMode->setIcon(QIcon::fromTheme("view-split-top-bottom")); } else { horiz_splitter->setOrientation(Qt::Vertical); KrActions::actVerticalMode->setText(i18n("Horizontal Mode")); KrActions::actVerticalMode->setIcon(QIcon::fromTheme("view-split-left-right")); } } void KrusaderView::saveSettings(KConfigGroup &cfg) { QList lst = horiz_splitter->sizes(); cfg.writeEntry("Splitter Sizes", lst); QList vertSplitterSizes = _terminalDock->isVisible() && !isTerminalEmulatorFullscreen() // fix sizes() not returning correct values on fullscreen+shutdown && vert_splitter->sizes().first() != 0 ? vert_splitter->sizes() : verticalSplitterSizes; cfg.writeEntry("Terminal Emulator Splitter Sizes", vertSplitterSizes); cfg.writeEntry("Vertical Mode", isVertical()); cfg.writeEntry("Left Side Is Active", ACTIVE_PANEL->gui->isLeft()); leftMng->saveSettings(KConfigGroup(&cfg, "Left Tab Bar"), true); rightMng->saveSettings(KConfigGroup(&cfg, "Right Tab Bar"), true); } bool KrusaderView::cursorIsOnOtherSide(PanelManager *of, const QPoint &globalPos) { int border = -1; int pos = -1; if (horiz_splitter->orientation() == Qt::Horizontal) { pos = globalPos.x(); if(of == leftMng) border = leftMng->mapToGlobal(QPoint(leftMng->width(), 0)).x(); else border = rightMng->mapToGlobal(QPoint(0, 0)).x(); } else { pos = globalPos.y(); if(of == leftMng) border = leftMng->mapToGlobal(QPoint(0, leftMng->height())).y(); else border = rightMng->mapToGlobal(QPoint(0, 0)).y(); } return (of == leftMng) ? pos > border : pos < border; } void KrusaderView::draggingTab(PanelManager *from, QMouseEvent *e) { QString icon; if (horiz_splitter->orientation() == Qt::Horizontal) icon = (from == leftMng) ? "arrow-right" : "arrow-left"; else icon = (from == leftMng) ? "arrow-down" : "arrow-up"; QCursor cursor(QIcon::fromTheme(icon).pixmap(22)); if (cursorIsOnOtherSide(from, e->globalPos())) { if(!qApp->overrideCursor()) qApp->setOverrideCursor(cursor); } else qApp->restoreOverrideCursor(); } void KrusaderView::draggingTabFinished(PanelManager *from, QMouseEvent *e) { qApp->restoreOverrideCursor(); if (cursorIsOnOtherSide(from, e->globalPos())) from->moveTabToOtherSide(); } diff --git a/krusader/main.cpp b/krusader/main.cpp index 0a203ee8..03417659 100644 --- a/krusader/main.cpp +++ b/krusader/main.cpp @@ -1,345 +1,344 @@ /*************************************************************************** main.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include #include // QtCore #include #include #include #include #include #include // QtGui #include // QtDBus #include #include // QtWidgets #include #include #include #include #include #include #include #include "../Archive/krarchandler.h" #include "krusader.h" #include "krusaderview.h" #include "panelmanager.h" #include "krusaderversion.h" #include "krslots.h" #include "defaults.h" -#include "Panel/krviewfactory.h" static const char *description = I18N_NOOP("Krusader\nTwin-Panel File Manager by KDE"); static void sigterm_handler(int i) { fprintf(stderr, "Signal: %d\n", i); QAbstractEventDispatcher *instance = QAbstractEventDispatcher::instance(); if (instance) instance->wakeUp(); QApplication::exit(- 15); } void openTabsRemote(QStringList tabs, bool left, QString appName) { // make sure left or right are not relative paths for (int i = 0; i != tabs.count(); i++) { tabs[ i ] = tabs[ i ].trimmed(); if (!tabs[ i ].startsWith('/') && tabs[ i ].indexOf(":/") < 0) tabs[ i ] = QDir::currentPath() + '/' + tabs[ i ]; } QDBusInterface remoteApp("org.krusader", "/Instances/" + appName + (left ? "/left_manager" : "/right_manager"), "org.krusader.PanelManager", QDBusConnection::sessionBus()); QDBusReply reply; if (remoteApp.isValid()) reply = remoteApp.call("newTabs", tabs); if (!reply.isValid()) fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); } //! An object that manages archives in several parts of the source code. KRarcHandler arcHandler; int main(int argc, char *argv[]) { // ============ begin icon-stuff =========== // If the user has no icon specified over the commandline we set up our own. // this is according to the users privileges. The icons are in Krusader::privIcon() /* bool hasIcon = false; int i = 0; char * myArgv[argc+2];*/ // if no --miniicon is given, --icon is used. So we don't need to check for --miniicon separately /* for (i = 0; i < argc; ++i) { if (strstr(argv[ i ], "-icon") != 0) // important: just one dash because both can appear! hasIcon = true; } static const char* const icon_text = "--icon"; const char* icon_name = Krusader::privIcon(); char addedParams[strlen(icon_text)+strlen(icon_name)+2]; if (! hasIcon) { for (i = 0; i < argc; ++i) myArgv[ i ] = argv[ i ]; strcpy(addedParams, icon_text); strcpy(addedParams + strlen(icon_text) + 1, icon_name); myArgv[ argc ] = addedParams; myArgv[ ++argc ] = addedParams + strlen(icon_text) + 1; myArgv[ ++argc ] = 0; argv = myArgv; }*/ // ============ end icon-stuff =========== // prevent qt5-webengine crashing QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); // create the application and set application domain so that calls to i18n get strings from right place. QApplication app(argc, argv); KLocalizedString::setApplicationDomain("krusader"); // ABOUT data information #ifdef RELEASE_NAME QString versionName = QString("%1 \"%2\"").arg(VERSION).arg(RELEASE_NAME); #else QString versionName = VERSION; #endif KAboutData aboutData(QStringLiteral("krusader"), (geteuid() ? i18n("Krusader") : i18n("Krusader - ROOT PRIVILEGES")), versionName, i18n(description), KAboutLicense::GPL_V2, i18n("(c) 2000-2003, Shie Erlich, Rafi Yanai\n(c) 2004-2016, Krusader Krew"), i18n("Feedback:\nhttps://forum.kde.org/viewforum.php?f=225\n\nIRC\nserver: " "irc.freenode.net, channel: #krusader"), QStringLiteral("https://krusader.org")); aboutData.setOrganizationDomain(QByteArray("kde.org")); aboutData.setDesktopFileName(QStringLiteral("org.kde.krusader")); aboutData.addAuthor(i18n("Rafi Yanai"), i18n("Author (retired)"), QStringLiteral("yanai@users.sourceforge.net")); aboutData.addAuthor(i18n("Shie Erlich"), i18n("Author (retired)"), QStringLiteral("erlich@users.sourceforge.net")); aboutData.addAuthor(i18n("Jan Lepper"), i18n("Developer"), QStringLiteral("jan_lepper@gmx.de"), 0); aboutData.addAuthor(i18n("Andrey Matveyakin"), i18n("Developer"), QStringLiteral("a.matveyakin@gmail.com"), 0); aboutData.addAuthor(i18n("Simon Persson"), i18n("Developer"), QStringLiteral("simon.persson@mykolab.com"), 0); aboutData.addAuthor(i18n("Davide Gianforte"), i18n("Developer"), QStringLiteral("davide@gengisdave.org"), 0); aboutData.addAuthor(i18n("Toni Asensi Esteve"), i18n("Developer"), QStringLiteral("toni.asensi@kdemail.net"), 0); aboutData.addAuthor(i18n("Alexander Bikadorov"), i18n("Developer"), QStringLiteral("alex.bikadorov@kdemail.net"), 0); aboutData.addAuthor(i18n("Karai Csaba"), i18n("Developer (retired)"), QStringLiteral("ckarai@users.sourceforge.net"), 0); aboutData.addAuthor(i18n("Heiner Eichmann"), i18n("Developer (retired)"), QStringLiteral("h.eichmann@gmx.de"), 0); aboutData.addAuthor(i18n("Jonas Bähr"), i18n("Developer (retired)"), QStringLiteral("jonas.baehr@web.de"), 0); aboutData.addAuthor(i18n("Václav Jůza"), i18n("Developer (retired)"), QStringLiteral("vaclavjuza@gmail.com"), 0); aboutData.addAuthor(i18n("Dirk Eschler"), i18n("Webmaster (retired)"), QStringLiteral("deschler@users.sourceforge.net"), 0); aboutData.addAuthor(i18n("Frank Schoolmeesters"), i18n("Documentation and marketing coordinator (retired)"), QStringLiteral("frank_schoolmeesters@yahoo.com"), 0); aboutData.addAuthor(i18n("Richard Holt"), i18n("Documentation & Proofing (retired)"), QStringLiteral("richard.holt@gmail.com"), 0); aboutData.addAuthor(i18n("Matej Urbancic"), i18n("Marketing & Product Research (retired)"), QStringLiteral("matej.urban@gmail.com"), 0); aboutData.addCredit(i18n("kde.org"), i18n("Everyone involved in KDE"), 0, 0); aboutData.addCredit(i18n("l10n.kde.org"), i18n("KDE Translation Teams"), 0, 0); aboutData.addCredit(i18n("Jiří Paleček"), i18n("QA, bug-hunting, patches and general help"), QStringLiteral("jpalecek@web.de"), 0); aboutData.addCredit(i18n("Jiří Klement"), i18n("Important help in KDE 4 porting"), 0, 0); aboutData.addCredit(i18n("Andrew Neupokoev"), i18n("Killer Logo and Icons for Krusader (contest winner)"), QStringLiteral("doom-blue@yandex.ru"), 0); aboutData.addCredit(i18n("The UsefulArts Organization"), i18n("Icon for Krusader"), QStringLiteral("mail@usefularts.org"), 0); aboutData.addCredit(i18n("Gábor Lehel"), i18n("Viewer module for 3rd Hand"), QStringLiteral("illissius@gmail.com"), 0); aboutData.addCredit(i18n("Mark Eatough"), i18n("Handbook Proof-Reader"), QStringLiteral("markeatough@yahoo.com"), 0); aboutData.addCredit(i18n("Jan Halasa"), i18n("The old Bookmark Module"), QStringLiteral("xhalasa@fi.muni.cz"), 0); aboutData.addCredit(i18n("Hans Löffler"), i18n("Dir history button"), 0, 0); aboutData.addCredit(i18n("Szombathelyi György"), i18n("ISO KIO slave"), 0, 0); aboutData.addCredit(i18n("Jan Willem van de Meent (Adios)"), i18n("Icons for Krusader"), QStringLiteral("janwillem@lorentz.leidenuniv.nl"), 0); aboutData.addCredit(i18n("Mikolaj Machowski"), i18n("Usability and QA"), QStringLiteral(""), 0); aboutData.addCredit(i18n("Cristi Dumitrescu"), i18n("QA, bug-hunting, patches and general help"), QStringLiteral("cristid@chip.ro"), 0); aboutData.addCredit(i18n("Aurelien Gateau"), i18n("patch for KViewer"), QStringLiteral("aurelien.gateau@free.fr"), 0); aboutData.addCredit(i18n("Milan Brabec"), i18n("the first patch ever!"), QStringLiteral("mbrabec@volny.cz"), 0); aboutData.addCredit(i18n("Asim Husanovic"), i18n("Bosnian translation"), QStringLiteral("asim@megatel.ba"), 0); aboutData.addCredit(i18n("Doutor Zero"), i18n("Brazilian Portuguese translation"), QStringLiteral("doutor.zero@gmail.com"), 0); aboutData.addCredit(i18n("Milen Ivanov"), i18n("Bulgarian translation"), QStringLiteral("milen.ivanov@abv.bg"), 0); aboutData.addCredit(i18n("Quim Perez"), i18n("Catalan translation"), QStringLiteral("noguer@osona.com"), 0); aboutData.addCredit(i18n("Jinghua Luo"), i18n("Chinese Simplified translation"), QStringLiteral("luojinghua@msn.com"), 0); aboutData.addCredit(i18n("Mitek"), i18n("Old Czech translation"), QStringLiteral("mitek@email.cz"), 0); aboutData.addCredit(i18n("Martin Sixta"), i18n("Old Czech translation"), QStringLiteral("lukumo84@seznam.cz"), 0); aboutData.addCredit(i18n("Vaclav Jůza"), i18n("Czech translation"), QStringLiteral("VaclavJuza@gmail.com"), 0); aboutData.addCredit(i18n("Anders Bruun Olsen"), i18n("Old Danish translation"), QStringLiteral("anders@bruun-olsen.net"), 0); aboutData.addCredit(i18n("Peter H. Sorensen"), i18n("Danish translation"), QStringLiteral("peters@skydebanen.net"), 0); aboutData.addCredit(i18n("Frank Schoolmeesters"), i18n("Dutch translation"), QStringLiteral("frank_schoolmeesters@yahoo.com"), 0); aboutData.addCredit(i18n("Rene-Pierre Lehmann"), i18n("Old French translation"), QStringLiteral("ripi@lepi.org"), 0); aboutData.addCredit(i18n("David Guillerm"), i18n("French translation"), QStringLiteral("dguillerm@gmail.com"), 0); aboutData.addCredit(i18n("Christoph Thielecke"), i18n("Old German translation"), QStringLiteral("crissi99@gmx.de"), 0); aboutData.addCredit(i18n("Dirk Eschler"), i18n("German translation"), QStringLiteral("deschler@users.sourceforge.net"), 0); aboutData.addCredit(i18n("Spiros Georgaras"), i18n("Greek translation"), QStringLiteral("sngeorgaras@gmail.com"), 0); aboutData.addCredit(i18n("Kukk Zoltan"), i18n("Old Hungarian translation"), QStringLiteral("kukkzoli@freemail.hu"), 0); aboutData.addCredit(i18n("Arpad Biro"), i18n("Hungarian translation"), QStringLiteral("biro_arpad@yahoo.com"), 0); aboutData.addCredit(i18n("Giuseppe Bordoni"), i18n("Italian translation"), QStringLiteral("geppo@geppozone.com"), 0); aboutData.addCredit(i18n("Hideki Kimura"), i18n("Japanese translation"), QStringLiteral("hangyo1973@gmail.com"), 0); aboutData.addCredit(i18n("UTUMI Hirosi"), i18n("Old Japanese translation"), QStringLiteral("utuhiro@mx12.freecom.ne.jp"), 0); aboutData.addCredit(i18n("Dovydas Sankauskas"), i18n("Lithuanian translation"), QStringLiteral("laisve@gmail.com"), 0); aboutData.addCredit(i18n("Bruno Queiros"), i18n("Portuguese translation"), QStringLiteral("brunoqueiros@portugalmail.com"), 0); aboutData.addCredit(i18n("Lukasz Janyst"), i18n("Old Polish translation"), QStringLiteral("ljan@wp.pl"), 0); aboutData.addCredit(i18n("Pawel Salawa"), i18n("Polish translation"), QStringLiteral("boogie@myslenice.one.pl"), 0); aboutData.addCredit(i18n("Tomek Grzejszczyk"), i18n("Polish translation"), QStringLiteral("tgrzej@onet.eu"), 0); aboutData.addCredit(i18n("Dmitry A. Bugay"), i18n("Russian translation"), QStringLiteral("sam@vhnet.ru"), 0); aboutData.addCredit(i18n("Dmitry Chernyak"), i18n("Old Russian translation"), QStringLiteral("chernyak@mail.ru"), 0); aboutData.addCredit(i18n("Sasa Tomic"), i18n("Serbian translation"), QStringLiteral("stomic@gmx.net"), 0); aboutData.addCredit(i18n("Zdenko Podobný and Ondrej Pačay (Yogi)"), i18n("Slovak translation"), QStringLiteral("zdenop@gmail.com"), 0); aboutData.addCredit(i18n("Matej Urbancic"), i18n("Slovenian translation"), QStringLiteral("matej.urban@gmail.com"), 0); aboutData.addCredit(i18n("Rafael Munoz"), i18n("Old Spanish translation"), QStringLiteral("muror@hotpop.com"), 0); aboutData.addCredit(i18n("Alejandro Araiza Alvarado"), i18n("Spanish translation"), QStringLiteral("mebrelith@gmail.com"), 0); aboutData.addCredit(i18n("Erik Johanssen"), i18n("Old Swedish translation"), QStringLiteral("erre@telia.com"), 0); aboutData.addCredit(i18n("Anders Linden"), i18n("Old Swedish translation"), QStringLiteral("connyosis@gmx.net"), 0); aboutData.addCredit(i18n("Peter Landgren"), i18n("Swedish translation"), QStringLiteral("peter.talken@telia.com"), 0); aboutData.addCredit(i18n("Bekir Sonat"), i18n("Turkish translation"), QStringLiteral("bekirsonat@kde.org.tr"), 0); aboutData.addCredit(i18n("Ivan Petrouchtchak"), i18n("Ukrainian translation"), QStringLiteral("connyosis@gmx.net"), 0); aboutData.addCredit(i18n("Seongnam Jee"), i18n("Korean translation"), QStringLiteral("snjee@intellicam.com"), 0); // This will call QCoreApplication::setApplicationName, etc for us by using info in the KAboutData instance. // The only thing not called for us is setWindowIcon(), which is why we do it ourselves here. KAboutData::setApplicationData(aboutData); app.setWindowIcon(QIcon::fromTheme(Krusader::privIcon())); // Command line arguments ... QCommandLineParser parser; aboutData.setupCommandLine(&parser); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("left"), i18n("Start left panel at "), QLatin1String("path"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("right"), i18n("Start right panel at "), QLatin1String("path"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("profile"), i18n("Load this profile on startup"), QLatin1String("panel-profile"))); parser.addPositionalArgument(QLatin1String("url"), i18n("URL to open")); // check for command line arguments parser.process(app); aboutData.processCommandLine(&parser); KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Look&Feel")); bool singleInstanceMode = cfg.readEntry("Single Instance Mode", _SingleInstanceMode); QString url; if(!parser.positionalArguments().isEmpty()) { url = parser.positionalArguments().first(); } QString appName = "krusader"; if (!singleInstanceMode) appName += QString("%1").arg(getpid()); if (!QDBusConnection::sessionBus().isConnected()) { fprintf(stderr, "Cannot connect to the D-BUS session bus.\n" "To start it, run:\n" "\teval `dbus-launch --auto-syntax`\n"); } if (singleInstanceMode) { QDBusInterface remoteApp("org.krusader", "/Instances/" + appName, "org.krusader.Instance", QDBusConnection::sessionBus()); QDBusReply reply; if (remoteApp.isValid()) reply = remoteApp.call("isRunning"); if (!reply.isValid() && reply.error().type() != QDBusError::ServiceUnknown && reply.error().type() != QDBusError::UnknownObject) fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); if (reply.isValid() && (bool)reply) { KStartupInfo::appStarted(); QStringList tabs; if (parser.isSet("left")) openTabsRemote(parser.value("left").split(','), true, appName); if (parser.isSet("right")) openTabsRemote(parser.value("right").split(','), false, appName); if(!url.isEmpty()) { reply = remoteApp.call("openUrl", url); if (!reply.isValid()) fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); } return 0; } } // splash screen - if the user wants one QSplashScreen *splash = 0; { // don't remove bracket KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Look&Feel")); if (cfg.readEntry("Show splashscreen", _ShowSplashScreen)) { QString splashFilename = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("splash.png")); QPixmap pixmap(splashFilename); if (!pixmap.isNull()) { splash = new QSplashScreen(pixmap); splash->show(); } } } // don't remove bracket Krusader::AppName = appName; Krusader *krusader = new Krusader(parser); if(!url.isEmpty()) krusader->openUrl(url); QDBusConnection dbus = QDBusConnection::sessionBus(); if (!dbus.interface()->isServiceRegistered("org.krusader") && !dbus.registerService("org.krusader")) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } if (!dbus.registerObject("/Instances/" + appName, krusader, QDBusConnection::ExportScriptableSlots)) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } if (!dbus.registerObject("/Instances/" + appName + "/left_manager", LEFT_MNG, QDBusConnection::ExportScriptableSlots)) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } if (!dbus.registerObject("/Instances/" + appName + "/right_manager", RIGHT_MNG, QDBusConnection::ExportScriptableSlots)) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } // catching SIGTERM, SIGHUP, SIGQUIT signal(SIGTERM, sigterm_handler); signal(SIGPIPE, sigterm_handler); signal(SIGHUP, sigterm_handler); QObject::connect(&app, &QGuiApplication::applicationStateChanged, SLOTS, &KRslots::applicationStateChanged); // hide splashscreen if (splash) { splash->finish(krusader); delete splash; } // let's go. return app.exec(); } diff --git a/krusader/panelmanager.cpp b/krusader/panelmanager.cpp index c7901c06..57b74b8a 100644 --- a/krusader/panelmanager.cpp +++ b/krusader/panelmanager.cpp @@ -1,450 +1,450 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "panelmanager.h" #include "defaults.h" #include "tabactions.h" #include "krusaderview.h" #include "krmainwindow.h" #include "Panel/listpanel.h" #include "Panel/panelfunc.h" -#include "Panel/krviewfactory.h" +#include "Panel/PanelView/krviewfactory.h" #include // QtGui #include // QtWidgets #include #include #include #include #include #include PanelManager::PanelManager(QWidget *parent, KrMainWindow* mainWindow, bool left) : QWidget(parent), _otherManager(0), _actions(mainWindow->tabActions()), _layout(0), _left(left), _self(0) { _layout = new QGridLayout(this); _layout->setContentsMargins(0, 0, 0, 0); _layout->setSpacing(0); _stack = new QStackedWidget(this); // new tab button _newTab = new QToolButton(this); _newTab->setAutoRaise(true); _newTab->setText(i18n("Open a new tab in home")); _newTab->setToolTip(i18n("Open a new tab in home")); _newTab->setIcon(SmallIcon("tab-new")); _newTab->adjustSize(); connect(_newTab, SIGNAL(clicked()), this, SLOT(slotNewTab())); // tab-bar _tabbar = new PanelTabBar(this, _actions); connect(_tabbar, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentTabChanged(int))); connect(_tabbar, SIGNAL(tabCloseRequested(int)), this, SLOT(slotCloseTab(int))); connect(_tabbar, SIGNAL(closeCurrentTab()), this, SLOT(slotCloseTab())); connect(_tabbar, SIGNAL(newTab(QUrl)), this, SLOT(slotNewTab(QUrl))); connect(_tabbar, SIGNAL(draggingTab(QMouseEvent*)), this, SLOT(slotDraggingTab(QMouseEvent*))); connect(_tabbar, SIGNAL(draggingTabFinished(QMouseEvent*)), this, SLOT(slotDraggingTabFinished(QMouseEvent*))); QHBoxLayout *tabbarLayout = new QHBoxLayout; tabbarLayout->setSpacing(0); tabbarLayout->setContentsMargins(0, 0, 0, 0); tabbarLayout->addWidget(_tabbar); tabbarLayout->addWidget(_newTab); _layout->addWidget(_stack, 0, 0); _layout->addLayout(tabbarLayout, 1, 0); updateTabbarPos(); setLayout(_layout); addPanel(true); tabsCountChanged(); } void PanelManager::tabsCountChanged() { const KConfigGroup cfg(krConfig, "Look&Feel"); const bool showTabbar = _tabbar->count() > 1 || cfg.readEntry("Show Tab Bar On Single Tab", true); const bool showButtons = showTabbar && cfg.readEntry("Show Tab Buttons", true); _tabbar->setVisible(showTabbar); _newTab->setVisible(showButtons); // disable close button if only 1 tab is left _tabbar->setTabsClosable(showButtons && _tabbar->count() > 1); _actions->refreshActions(); } void PanelManager::activate() { assert(sender() == (currentPanel()->gui)); emit setActiveManager(this); _actions->refreshActions(); } void PanelManager::slotCurrentTabChanged(int index) // void PanelManager::slotChangePanel(ListPanel *p, bool makeActive) { ListPanel *p = _tabbar->getPanel(index); if (!p || p == _self) return; ListPanel *prev = _self; _self = p; _stack->setCurrentWidget(_self); if(prev) prev->slotFocusOnMe(false); //FIXME - necessary ? _self->slotFocusOnMe(this == ACTIVE_MNG); emit pathChanged(p); if(otherManager()) otherManager()->currentPanel()->otherPanelChanged(); } ListPanel* PanelManager::createPanel(KConfigGroup cfg) { ListPanel * p = new ListPanel(_stack, this, cfg); connectPanel(p); return p; } void PanelManager::connectPanel(ListPanel *p) { connect(p, &ListPanel::activate, this, &PanelManager::activate); connect(p, &ListPanel::pathChanged, this, [=]() { pathChanged(p); }); connect(p, &ListPanel::pathChanged, this, [=]() { _tabbar->updateTab(p); }); } void PanelManager::disconnectPanel(ListPanel *p) { disconnect(p, &ListPanel::activate, this, nullptr); disconnect(p, &ListPanel::pathChanged, this, nullptr); } ListPanel* PanelManager::addPanel(bool setCurrent, KConfigGroup cfg, KrPanel *nextTo) { // create the panel and add it into the widgetstack ListPanel * p = createPanel(cfg); _stack->addWidget(p); // now, create the corresponding tab int index = _tabbar->addPanel(p, setCurrent, nextTo); tabsCountChanged(); if (setCurrent) slotCurrentTabChanged(index); return p; } void PanelManager::saveSettings(KConfigGroup config, bool saveHistory) { config.writeEntry("ActiveTab", activeTab()); KConfigGroup grpTabs(&config, "Tabs"); foreach(const QString &grpTab, grpTabs.groupList()) grpTabs.deleteGroup(grpTab); for(int i = 0; i < _tabbar->count(); i++) { ListPanel *panel = _tabbar->getPanel(i); KConfigGroup grpTab(&grpTabs, "Tab" + QString::number(i)); panel->saveSettings(grpTab, saveHistory); } } void PanelManager::loadSettings(KConfigGroup config) { KConfigGroup grpTabs(&config, "Tabs"); int numTabsOld = _tabbar->count(); int numTabsNew = grpTabs.groupList().count(); for(int i = 0; i < numTabsNew; i++) { KConfigGroup grpTab(&grpTabs, "Tab" + QString::number(i)); // TODO workaround for bug 371453. Remove this when bug is fixed if (grpTab.keyList().isEmpty()) continue; ListPanel *panel = i < numTabsOld ? _tabbar->getPanel(i) : addPanel(false, grpTab); panel->restoreSettings(grpTab); _tabbar->updateTab(panel); } for(int i = numTabsOld - 1; i >= numTabsNew && i > 0; i--) slotCloseTab(i); setActiveTab(config.readEntry("ActiveTab", 0)); // this is needed so that all tab labels get updated layoutTabs(); } void PanelManager::layoutTabs() { // delayed url refreshes may be pending - // delay the layout too so it happens after them QTimer::singleShot(0, _tabbar, SLOT(layoutTabs())); } void PanelManager::moveTabToOtherSide() { if(tabCount() < 2) return; ListPanel *p; _tabbar->removeCurrentPanel(p); _stack->removeWidget(p); disconnectPanel(p); p->reparent(_otherManager->_stack, _otherManager); _otherManager->connectPanel(p); _otherManager->_stack->addWidget(p); _otherManager->_tabbar->addPanel(p, true); _otherManager->tabsCountChanged(); tabsCountChanged(); p->slotFocusOnMe(); } void PanelManager::slotNewTab(const QUrl &url, bool setCurrent, KrPanel *nextTo) { ListPanel *p = addPanel(setCurrent, KConfigGroup(), nextTo); if(nextTo && nextTo->gui) { // We duplicate tab settings by writing original settings to a temporary // group and making the new tab read settings from it. Duplicating // settings directly would add too much complexity. QString grpName = "PanelManager_" + QString::number(qApp->applicationPid()); krConfig->deleteGroup(grpName); // make sure the group is empty KConfigGroup cfg(krConfig, grpName); nextTo->gui->saveSettings(cfg, true); p->restoreSettings(cfg); krConfig->deleteGroup(grpName); // reset undesired duplicated settings p->setLocked(false); } else p->start(url); } void PanelManager::slotNewTab() { slotNewTab(QUrl::fromLocalFile(QDir::home().absolutePath())); } void PanelManager::slotCloseTab() { slotCloseTab(_tabbar->currentIndex()); } void PanelManager::slotCloseTab(int index) { if (_tabbar->count() <= 1) /* if this is the last tab don't close it */ return ; ListPanel *oldp; // if (index == _tabbar->currentIndex()) // slotChangePanel(_tabbar->removeCurrentPanel(oldp), false); // else _tabbar->removePanel(index, oldp); //this automatically changes the current panel _stack->removeWidget(oldp); deletePanel(oldp); tabsCountChanged(); } void PanelManager::updateTabbarPos() { KConfigGroup group(krConfig, "Look&Feel"); if(group.readEntry("Tab Bar Position", "bottom") == "top") { _layout->addWidget(_stack, 2, 0); _tabbar->setShape(QTabBar::RoundedNorth); } else { _layout->addWidget(_stack, 0, 0); _tabbar->setShape(QTabBar::RoundedSouth); } } int PanelManager::activeTab() { return _tabbar->currentIndex(); } void PanelManager::setActiveTab(int index) { _tabbar->setCurrentIndex(index); } void PanelManager::slotRecreatePanels() { updateTabbarPos(); for (int i = 0; i != _tabbar->count(); i++) { QString grpName = "PanelManager_" + QString::number(qApp->applicationPid()); krConfig->deleteGroup(grpName); // make sure the group is empty KConfigGroup cfg(krConfig, grpName); ListPanel *oldPanel = _tabbar->getPanel(i); oldPanel->saveSettings(cfg, true); disconnect(oldPanel); ListPanel *newPanel = createPanel(cfg); _stack->insertWidget(i, newPanel); _tabbar->changePanel(i, newPanel); if (_self == oldPanel) { _self = newPanel; _stack->setCurrentWidget(_self); } _stack->removeWidget(oldPanel); deletePanel(oldPanel); newPanel->restoreSettings(cfg); _tabbar->updateTab(newPanel); krConfig->deleteGroup(grpName); } tabsCountChanged(); _self->slotFocusOnMe(this == ACTIVE_MNG); emit pathChanged(_self); } void PanelManager::slotNextTab() { int currTab = _tabbar->currentIndex(); int nextInd = (currTab == _tabbar->count() - 1 ? 0 : currTab + 1); _tabbar->setCurrentIndex(nextInd); } void PanelManager::slotPreviousTab() { int currTab = _tabbar->currentIndex(); int nextInd = (currTab == 0 ? _tabbar->count() - 1 : currTab - 1); _tabbar->setCurrentIndex(nextInd); } void PanelManager::refreshAllTabs() { int i = 0; while (i < _tabbar->count()) { ListPanel *panel = _tabbar->getPanel(i); if (panel) { panel->func->refresh(); } ++i; } } void PanelManager::deletePanel(ListPanel * p) { disconnect(p); delete p; } void PanelManager::slotCloseInactiveTabs() { int i = 0; while (i < _tabbar->count()) { if (i == activeTab()) i++; else slotCloseTab(i); } } void PanelManager::slotCloseDuplicatedTabs() { int i = 0; while (i < _tabbar->count() - 1) { ListPanel * panel1 = _tabbar->getPanel(i); if (panel1 != 0) { for (int j = i + 1; j < _tabbar->count(); j++) { ListPanel * panel2 = _tabbar->getPanel(j); if (panel2 != 0 && panel1->virtualPath().matches(panel2->virtualPath(), QUrl::StripTrailingSlash)) { if (j == activeTab()) { slotCloseTab(i); i--; break; } else { slotCloseTab(j); j--; } } } } i++; } } int PanelManager::findTab(QUrl url) { url.setPath(QDir::cleanPath(url.path())); for(int i = 0; i < _tabbar->count(); i++) { if(_tabbar->getPanel(i)) { QUrl panelUrl = _tabbar->getPanel(i)->virtualPath(); panelUrl.setPath(QDir::cleanPath(panelUrl.path())); if(panelUrl.matches(url, QUrl::StripTrailingSlash)) return i; } } return -1; } void PanelManager::slotLockTab() { ListPanel *panel = _self; panel->gui->setLocked(!panel->gui->isLocked()); _actions->refreshActions(); _tabbar->updateTab(panel); } void PanelManager::newTabs(const QStringList& urls) { for(int i = 0; i < urls.count(); i++) slotNewTab(QUrl::fromUserInput(urls[i], QString(), QUrl::AssumeLocalFile)); } KrPanel *PanelManager::currentPanel() { return _self; }