Example #1
1
DISABLE_COMPILER_WARNINGS
#include <QApplication>
#include <QDragMoveEvent>
#include <QHeaderView>
#include <QKeyEvent>
#include <QMouseEvent>
RESTORE_COMPILER_WARNINGS

#include <time.h>
#include <set>

#if defined __linux__ || defined __APPLE__
#include "cfocusframestyle.h"
#endif

CFileListView::CFileListView(QWidget *parent) :
	QTreeView(parent),
	_controller(CController::get()),
	_panelPosition(UnknownPanel),
	_bHeaderAdjustmentRequired(true),
	_singleMouseClickValid(false),
	_shiftPressedItemSelected(false)
{
	setMouseTracking(true);
	setItemDelegate(new CFileListItemDelegate);
	connect(this, &QTreeView::doubleClicked, [this](const QModelIndex &idx) {

		_itemUnderCursorBeforeMouseClick = QModelIndex();
		_singleMouseClickValid = false;

		for(FileListViewEventObserver* observer: _eventObservers)
		{
			if (observer->fileListReturnPressOrDoubleClickPerformed(idx))
				break;
		}
	});

	QHeaderView * headerView = header();
	assert_r(headerView);

	headerView->installEventFilter(this);

#if defined __linux__ || defined __APPLE__
	setStyle(new CFocusFrameStyle);
#endif
}
const std::vector<CMyHtmlParser::HtmlTag>& CMyHtmlParser::parse(const QByteArray& html)
{
	_tags.clear();

	_tree = myhtml_tree_create();
	assert_r(_tree);
	assert_r(myhtml_tree_init(_tree, _myhtmlInstance) == MyCORE_STATUS_OK);
	myhtml_callback_tree_node_insert_set(_tree, &CMyHtmlParser::callbackNodeInserted, this);

	/*
	* From Specification:
	*
	* The authoring conformance requirements for character encoding declarations limit them to only
	* appearing in the first 1024 bytes. User agents are therefore encouraged to use the prescan
	* algorithm below (as invoked by these steps) on the first 1024 bytes, but not to stall beyond that.
	*/
	_encoding = myencoding_prescan_stream_to_determine_encoding(html.data(), std::min(html.size(), 1024));
	if (_encoding == MyENCODING_NOT_DETERMINED)
	{
		assert_unconditional_r("Failed to determine data encoding");
		_encoding = MyENCODING_UTF_8;
	}

	assert_r(myhtml_parse(_tree, _encoding, html.data(), html.size()) == MyCORE_STATUS_OK);
	myhtml_tree_destroy(_tree);

	return _tags;
}
Example #3
0
void CController::openTerminal(const QString &folder)
{
#ifdef _WIN32
	const bool started = QProcess::startDetached(CShell::shellExecutable(), QStringList(), folder);
	assert_r(started);
#elif defined __APPLE__
	system(QString("osascript -e \"tell application \\\"Terminal\\\" to do script \\\"cd %1\\\"\"").arg(folder).toUtf8().data());
#elif defined __linux__
	const bool started = QProcess::startDetached(CShell::shellExecutable(), QStringList(), folder);
	assert_r(started);
#else
	#error unknown platform
#endif
}
Example #4
0
void CMainWindow::currentPanelChanged(QStackedWidget *panel)
{
	_currentPanelWidget = panel;
	_currentFileList = dynamic_cast<CPanelWidget*>(panel->widget(0));
	if (panel)
	{
		_otherPanelWidget = panel == ui->leftWidget ? ui->rightWidget : ui->leftWidget;
		_otherFileList = dynamic_cast<CPanelWidget*>(_otherPanelWidget->widget(0));
		assert_r(_otherPanelWidget && _otherFileList);
	}
	else
	{
		_otherPanelWidget = 0;
		_otherFileList = 0;
	}

	if (_currentFileList)
	{
		_controller->activePanelChanged(_currentFileList->panelPosition());
		CSettings().setValue(KEY_LAST_ACTIVE_PANEL, _currentFileList->panelPosition());
		ui->fullPath->setText(_controller->panel(_currentFileList->panelPosition()).currentDirPathNative());
		CPluginEngine::get().currentPanelChanged(_currentFileList->panelPosition());
		_commandLineCompleter.setModel(_currentFileList->sortModel());
	}
	else
		_commandLineCompleter.setModel(0);
}
Example #5
0
const QIcon& CIconProvider::iconFor(const CFileSystemObject& object)
{
	const qulonglong objectHash = hash(object);
	if (_iconForObject.count(objectHash) == 0)
	{
		const QIcon icon = _provider->iconFor(object);
		assert_r(!icon.isNull());

		const auto qimage = icon.pixmap(icon.availableSizes().front()).toImage();
		const qulonglong iconHash = fasthash64((const char*)qimage.constBits(), qimage.bytesPerLine() * qimage.height(), 0);

		if (_iconCache.size() > 300)
		{
			_iconCache.clear();
			_iconForObject.clear();
		}

		const auto iconInContainer = _iconCache.insert(std::make_pair(iconHash, icon)).first;
		_iconForObject[objectHash] = iconHash;
		
		return iconInContainer->second;
	}

	return _iconCache[_iconForObject[objectHash]];
}
Example #6
0
CMainWindow::CMainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::CMainWindow),
	_controller(new CController),
	_currentFileList(0),
	_otherFileList(0),
	_quickViewActive(false)
{
	assert_r(!_instance);
	_instance = this;
	ui->setupUi(this);

	connect(qApp, &QApplication::focusChanged, this, &CMainWindow::focusChanged);

	_controller->pluginProxy().setToolMenuEntryCreatorImplementation(CPluginProxy::CreateToolMenuEntryImplementationType(std::bind(&CMainWindow::createToolMenuEntries, this, std::placeholders::_1)));

	_currentFileList = ui->leftPanel;
	_otherFileList   = ui->rightPanel;

	connect(ui->leftPanel->fileListView(),  &CFileListView::ctrlEnterPressed, this, &CMainWindow::pasteCurrentFileName);
	connect(ui->rightPanel->fileListView(), &CFileListView::ctrlEnterPressed, this, &CMainWindow::pasteCurrentFileName);
	connect(ui->leftPanel->fileListView(),  &CFileListView::ctrlShiftEnterPressed, this, &CMainWindow::pasteCurrentFilePath);
	connect(ui->rightPanel->fileListView(), &CFileListView::ctrlShiftEnterPressed, this, &CMainWindow::pasteCurrentFilePath);

	connect(ui->leftPanel, &CPanelWidget::currentItemChangedSignal, this, &CMainWindow::currentItemChanged);
	connect(ui->rightPanel, &CPanelWidget::currentItemChangedSignal, this, &CMainWindow::currentItemChanged);

	connect(ui->leftPanel, &CPanelWidget::itemActivated, this, &CMainWindow::itemActivated);
	connect(ui->rightPanel, &CPanelWidget::itemActivated, this, &CMainWindow::itemActivated);

	ui->leftPanel->fileListView()->addEventObserver(this);
	ui->rightPanel->fileListView()->addEventObserver(this);

	initButtons();
	initActions();

	ui->leftPanel->setPanelPosition(LeftPanel);
	ui->rightPanel->setPanelPosition(RightPanel);

	ui->fullPath->clear();

	QSplitterHandle * handle = ui->splitter->handle(1);
	handle->setContextMenuPolicy(Qt::CustomContextMenu);
	connect(handle, &QSplitterHandle::customContextMenuRequested, this, &CMainWindow::splitterContextMenuRequested);

	connect(ui->commandLine, &CHistoryComboBox::itemActivated, this, &CMainWindow::executeCommand);

	_commandLineCompleter.setCaseSensitivity(Qt::CaseInsensitive);
	_commandLineCompleter.setCompletionMode(QCompleter::InlineCompletion);
	_commandLineCompleter.setCompletionColumn(NameColumn);
	ui->commandLine->setCompleter(&_commandLineCompleter);
	ui->commandLine->setClearEditorOnItemActivation(true);

	ui->leftWidget->setCurrentIndex(0); // PanelWidget
	ui->rightWidget->setCurrentIndex(0); // PanelWidget

	connect(&_uiThreadTimer, &QTimer::timeout, this, &CMainWindow::uiThreadTimerTick);
	_uiThreadTimer.start(5);
}
Example #7
0
void CController::setDisksChangedListener(CController::IDiskListObserver *listener)
{
	assert_r(std::find(_disksChangedListeners.begin(), _disksChangedListeners.end(), listener) == _disksChangedListeners.end());
	_disksChangedListeners.push_back(listener);

	// Force an update
	disksChanged();
}
Example #8
0
void CMainWindow::addToolMenuEntriesRecursively(CPluginProxy::MenuTree entry, QMenu* toolMenu)
{
	assert_r(toolMenu);
	QAction* action = toolMenu->addAction(entry.name);
	QObject::connect(action, &QAction::triggered, [entry](bool){entry.handler();});
	for(const auto& childEntry: entry.children)
		addToolMenuEntriesRecursively(childEntry, toolMenu);
}
std::vector<QString> CFileSystemObject::pathHierarchy(const QString& path)
{
	assert_r(!path.contains('\\'));
	assert_r(!path.contains(QStringLiteral("//")) || !path.rightRef(path.length() - 2).contains(QStringLiteral("//")));

	if (path.isEmpty())
		return {};
	else if (path == '/')
		return { QString('/') };


	QString pathItem = path.endsWith('/') ? path.left(path.length() - 1) : path;
	std::vector<QString> result {path == '/' ? QString() : path};
	while ((pathItem = QFileInfo(pathItem).absolutePath()).length() < result.back().length())
		result.push_back(pathItem);

	return result;
}
Example #10
0
void OsShell::executeShellCommand(const QString& command, const QString& workingDir)
{
	std::thread([command, workingDir](){
	#ifdef _WIN32
		_wsystem((QString("pushd ") + workingDir + " && " + command).toStdWString().data());
	#else
		const int result = std::system((QString("cd ") + workingDir + " && " + command).toUtf8().data());
		assert_r(result == 0);
	#endif
	}).detach();
}
void CFavoriteLocationsEditor::addLocationsToTreeWidget(std::list<CLocationsCollection>& parentList, std::list<CLocationsCollection>::iterator& locationCollectionListIterator, QTreeWidgetItem* parent)
{
	assert_r(locationCollectionListIterator->subLocations.empty() || locationCollectionListIterator->absolutePath.isEmpty());

	const bool isCategory = locationCollectionListIterator->absolutePath.isEmpty();
	CFavoriteLocationsListItem * treeWidgetItem = parent ? new CFavoriteLocationsListItem(parent, parentList, locationCollectionListIterator, isCategory) : new CFavoriteLocationsListItem(ui->_list, parentList, locationCollectionListIterator, isCategory);
	if (!locationCollectionListIterator->subLocations.empty())
		for (auto it = locationCollectionListIterator->subLocations.begin(); it != locationCollectionListIterator->subLocations.end(); ++it)
			addLocationsToTreeWidget(locationCollectionListIterator->subLocations, it, treeWidgetItem);

	if (isCategory)
		treeWidgetItem->setExpanded(true);
}
Example #12
0
bool prepareContextMenuForObjects(std::vector<std::wstring> objects, void * parentWindow, HMENU& hmenu, IContextMenu*& imenu)
{
	ComInitializer comInitializer;

	if (objects.empty())
		return false;

	std::vector<ITEMIDLIST*> ids;
	std::vector<LPCITEMIDLIST> relativeIds;
	IShellFolder * ifolder = 0;
	for (size_t i = 0; i < objects.size(); ++i)
	{
		std::replace(objects[i].begin(), objects[i].end(), '/', '\\');
		ids.push_back(0);
		HRESULT result = SHParseDisplayName(objects[i].c_str(), 0, &ids.back(), 0, 0);
		if (!SUCCEEDED(result) || !ids.back())
		{
			ids.pop_back();
			continue;
		}

		relativeIds.push_back(0);
		result = SHBindToParent(ids.back(), IID_IShellFolder, (void**)&ifolder, &relativeIds.back());
		if (!SUCCEEDED(result) || !relativeIds.back())
			relativeIds.pop_back();
		else if (i < objects.size() - 1 && ifolder)
		{
			ifolder->Release();
			ifolder = nullptr;
		}
	}

	CItemIdArrayReleaser arrayReleaser(ids);

	assert_r(parentWindow);
	assert_and_return_message_r(ifolder, "Error getting ifolder", false);
	assert_and_return_message_r(!relativeIds.empty(), "RelativeIds is empty", false);

	imenu = 0;
	HRESULT result = ifolder->GetUIObjectOf((HWND)parentWindow, (UINT)relativeIds.size(), (const ITEMIDLIST **)relativeIds.data(), IID_IContextMenu, 0, (void**)&imenu);
	if (!SUCCEEDED(result) || !imenu)
		return false;

	hmenu = CreatePopupMenu();
	if (!hmenu)
		return false;
	return (SUCCEEDED(imenu->QueryContextMenu(hmenu, 0, 1, 0x7FFF, CMF_NORMAL)));
}
Example #13
0
void CMainWindow::toggleQuickView()
{
	if (_quickViewActive)
	{
		_quickViewActive = false;
		assert_r(_currentPanelWidget->count() == 2 || _otherPanelWidget->count() == 2);
		if (_currentPanelWidget->count() == 2)
			_currentPanelWidget->removeWidget(_currentPanelWidget->widget(1));
		else
			_otherPanelWidget->removeWidget(_otherPanelWidget->widget(1));

		emit fileQuickVewFinished();
	}
	else
		quickViewCurrentFile();
}
Example #14
0
CController::CController() : _leftPanel(LeftPanel), _rightPanel(RightPanel), _workerThread(4, "CController worker thread")
{
	assert_r(_instance == nullptr); // Only makes sense to create one controller
	_instance = this;

	_diskEnumerator.addObserver(this);
	CPluginEngine::get().loadPlugins();

	_leftPanel.addPanelContentsChangedListener(&CPluginEngine::get());
	_rightPanel.addPanelContentsChangedListener(&CPluginEngine::get());

	// Manual update for the CPanels to get the disk list
	_diskEnumerator.updateSynchronously();

	_leftPanel.restoreFromSettings();
	_rightPanel.restoreFromSettings();
}
Example #15
0
void CMainWindow::quickViewCurrentFile()
{
	if (_quickViewActive)
	{
		assert_r(_otherPanelWidget->count() == 2);
		_otherPanelWidget->removeWidget(_otherPanelWidget->widget(1));
		emit fileQuickVewFinished();
	}

	CPluginWindow * viewerWindow = CPluginEngine::get().createViewerWindowForCurrentFile();
	if (!viewerWindow)
		return;

	connect(this, &CMainWindow::fileQuickVewFinished, viewerWindow, &CPluginWindow::deleteLater);

	_otherPanelWidget->setCurrentIndex(_otherPanelWidget->addWidget(viewerWindow->centralWidget()));
	_quickViewActive = true;
}
Example #16
0
// A current disk has been switched
bool CController::switchToDisk(Panel p, size_t index)
{
	assert_r(index < _diskEnumerator.drives().size());
	const QString drivePath = _diskEnumerator.drives().at(index).storageInfo.rootPath();

	FileOperationResultCode result = rcDirNotAccessible;
	if (drivePath == _diskEnumerator.drives().at(currentDiskIndex(otherPanelPosition(p))).storageInfo.rootPath())
	{
		result = setPath(p, otherPanel(p).currentDirPathNative(), refreshCauseOther);
	}
	else
	{
		const QString lastPathForDrive = CSettings().value(p == LeftPanel ? KEY_LAST_PATH_FOR_DRIVE_L.arg(drivePath.toHtmlEscaped()) : KEY_LAST_PATH_FOR_DRIVE_R.arg(drivePath.toHtmlEscaped()), drivePath).toString();
		result = setPath(p, lastPathForDrive, refreshCauseOther);
	}

	return result == rcOk;
}
DISABLE_COMPILER_WARNINGS
#include <QApplication>
#include <QKeyEvent>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QSortFilterProxyModel>
#include <QTextEdit>
#include <QTimer>
RESTORE_COMPILER_WARNINGS

// Item rename handling
void CFileListItemDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
{
	QStyledItemDelegate::setEditorData(editor, index);
	auto lineEditor = dynamic_cast<QLineEdit*>(editor);
	assert_r(lineEditor);
	assert_and_return_r(index.isValid(), );

	auto sortModel = dynamic_cast<const QSortFilterProxyModel*>(index.model());
	assert_and_return_message_r(sortModel, "Something has changed in the model hierarchy", );
	auto model = dynamic_cast<const CFileListModel*>(sortModel->sourceModel());
	assert_and_return_message_r(model, "Something has changed in the model hierarchy", );
	auto hash = model->itemHash(sortModel->mapToSource(index));
	const auto item = CController::get().itemByHash(model->panelPosition(), hash);

	if (item.isValid() && item.isFile())
	{
		const QString itemName = lineEditor->text();
		const int dot = itemName.lastIndexOf('.');
		if (dot != -1)
		{
			
			QTimer::singleShot(0, Qt::CoarseTimer, lineEditor, [=]() {
				lineEditor->setSelection(0, dot);
			});
		}
	}
}
Example #18
0
void CFileListView::selectRegion(const QModelIndex &start, const QModelIndex &end)
{
	bool itemBelongsToSelection = false;
	assert_r(selectionModel());
	for (int i = 0; i < model()->rowCount(); ++i)
	{
		// Start item found - beginning selection
		QModelIndex currentItem = model()->index(i, 0);
		if (!itemBelongsToSelection && (currentItem == start || currentItem == end))
		{
			itemBelongsToSelection = true;
			selectionModel()->select(currentItem, QItemSelectionModel::Select | QItemSelectionModel::Rows);
		}
		else if (itemBelongsToSelection && (currentItem == start || currentItem == end))
		{
			// End item found - finishing selection
			selectionModel()->select(currentItem, QItemSelectionModel::Select | QItemSelectionModel::Rows);
			return;
		}

		if (itemBelongsToSelection)
			selectionModel()->select(currentItem, QItemSelectionModel::Select | QItemSelectionModel::Rows);
	}
}
void CDiskEnumerator::addObserver(IDiskListObserver *observer)
{
	assert_r(std::find(_observers.begin(), _observers.end(), observer) == _observers.end());
	_observers.push_back(observer);
}
void CFileCommanderPlugin::setProxy(CPluginProxy *proxy)
{
	assert_r(proxy);
	_proxy = proxy;
	proxySet();
}
Example #21
0
bool OsShell::deleteItems(const std::vector<std::wstring>& items, bool moveToTrash, void * parentWindow)
{
	ComInitializer comInitializer;

	assert_r(parentWindow);
	std::vector<ITEMIDLIST*> idLists;
	for (auto& path: items)
	{
		__unaligned ITEMIDLIST* idl = ILCreateFromPathW(path.c_str());
		if (!idl)
		{
			for (auto& pid : idLists)
				ILFree(pid);

			qInfo() << "ILCreateFromPathW" << "failed for path" << QString::fromWCharArray(path.c_str());
			return false;
		}
		idLists.push_back(idl);
		assert_r(idLists.back());
	}

	IShellItemArray * iArray = 0;
	HRESULT result = SHCreateShellItemArrayFromIDLists((UINT)idLists.size(), (LPCITEMIDLIST*)idLists.data(), &iArray);

	// Freeing memory
	for (auto& pid: idLists)
		ILFree(pid);
	idLists.clear();

	if (!SUCCEEDED(result) || !iArray)
	{
		qInfo() << "SHCreateShellItemArrayFromIDLists failed";
		return false;
	}

	IFileOperation * iOperation = 0;
	result = CoCreateInstance(CLSID_FileOperation, 0, CLSCTX_ALL, IID_IFileOperation, (void**)&iOperation);
	if (!SUCCEEDED(result) || !iOperation)
	{
		qInfo() << "CoCreateInstance(CLSID_FileOperation, 0, CLSCTX_ALL, IID_IFileOperation, (void**)&iOperation) failed";
		return false;
	}

	result = iOperation->DeleteItems(iArray);
	if (!SUCCEEDED(result))
	{
		qInfo() << "DeleteItems failed";
	}
	else
	{
		if (moveToTrash)
		{
			result = iOperation->SetOperationFlags(FOF_ALLOWUNDO);
		}
		else
			result = iOperation->SetOperationFlags(FOF_WANTNUKEWARNING);

		if (!SUCCEEDED(result))
			qInfo() << "SetOperationFlags failed";

		result = iOperation->SetOwnerWindow((HWND) parentWindow);
		if (!SUCCEEDED(result))
			qInfo() << "SetOwnerWindow failed";

		result = iOperation->PerformOperations();
		if (!SUCCEEDED(result) && result != COPYENGINE_E_USER_CANCELLED)
		{
			qInfo() << "PerformOperations failed";
			if (result == COPYENGINE_E_REQUIRES_ELEVATION)
				qInfo() << "Elevation required";
		}
		else
			result = S_OK;
	}

	iOperation->Release();
	iArray->Release();
	return SUCCEEDED(result);
}
Example #22
0
CController& CController::get()
{
	assert_r(_instance);
	return *_instance;
}
Example #23
0
// Sets the position (left or right) of a panel that this model represents
void CFileListView::setPanelPosition(enum Panel p)
{
	assert_r(_panelPosition == UnknownPanel); // Doesn't make sense to call this method more than once
	_panelPosition = p;
}
Example #24
0
	ComInitializer() {
		const auto result = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
		assert_r(SUCCEEDED(result));
	}
Example #25
0
void CTimeElapsed::resume()
{
	assert_r(_paused);
	_paused = false;
	_pausedFor += std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - _pauseTimeStamp);
}
Example #26
0
void CTimeElapsed::pause()
{
	assert_r(!_paused);
	_pauseTimeStamp = std::chrono::high_resolution_clock::now();
	_paused = true;
}