mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Merge pull request #1195 from Nordsoft91/editor-drapndrop
This commit is contained in:
		| @@ -550,7 +550,7 @@ void MainWindow::loadObjectsTree() | ||||
|  | ||||
| 	//model | ||||
| 	objectsModel.setHorizontalHeaderLabels(QStringList() << tr("Type")); | ||||
| 	objectBrowser = new ObjectBrowser(this); | ||||
| 	objectBrowser = new ObjectBrowserProxyModel(this); | ||||
| 	objectBrowser->setSourceModel(&objectsModel); | ||||
| 	objectBrowser->setDynamicSortFilter(false); | ||||
| 	objectBrowser->setRecursiveFilteringEnabled(true); | ||||
| @@ -853,12 +853,11 @@ void MainWindow::on_toolErase_clicked() | ||||
| 	ui->tabWidget->setCurrentIndex(0); | ||||
| } | ||||
|  | ||||
| void MainWindow::preparePreview(const QModelIndex &index, bool createNew) | ||||
| void MainWindow::preparePreview(const QModelIndex &index) | ||||
| { | ||||
| 	scenePreview->clear(); | ||||
|  | ||||
| 	auto data = objectsModel.itemFromIndex(objectBrowser->mapToSource(index))->data().toJsonObject(); | ||||
|  | ||||
| 	if(!data.empty()) | ||||
| 	{ | ||||
| 		auto preview = data["preview"]; | ||||
| @@ -866,29 +865,12 @@ void MainWindow::preparePreview(const QModelIndex &index, bool createNew) | ||||
| 		{ | ||||
| 			QPixmap objPreview = pixmapFromJson(preview); | ||||
| 			scenePreview->addPixmap(objPreview); | ||||
|  | ||||
| 			auto objId = data["id"].toInt(); | ||||
| 			auto objSubId = data["subid"].toInt(); | ||||
| 			auto templateId = data["template"].toInt(); | ||||
|  | ||||
| 			if(controller.discardObject(mapLevel) || createNew) | ||||
| 			{ | ||||
| 				auto factory = VLC->objtypeh->getHandlerFor(objId, objSubId); | ||||
| 				auto templ = factory->getTemplates()[templateId]; | ||||
| 				controller.createObject(mapLevel, factory->create(templ)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void MainWindow::treeViewSelected(const QModelIndex & index, const QModelIndex & deselected) | ||||
| { | ||||
| 	preparePreview(index, false); | ||||
| } | ||||
|  | ||||
|  | ||||
| void MainWindow::on_treeView_activated(const QModelIndex &index) | ||||
| { | ||||
| 	ui->toolBrush->setChecked(false); | ||||
| 	ui->toolBrush2->setChecked(false); | ||||
| @@ -896,11 +878,10 @@ void MainWindow::on_treeView_activated(const QModelIndex &index) | ||||
| 	ui->toolArea->setChecked(false); | ||||
| 	ui->toolLasso->setChecked(false); | ||||
| 	ui->mapView->selectionTool = MapView::SelectionTool::None; | ||||
|  | ||||
| 	preparePreview(index, true); | ||||
| 	 | ||||
| 	preparePreview(index); | ||||
| } | ||||
|  | ||||
|  | ||||
| void MainWindow::on_terrainFilterCombo_currentTextChanged(const QString &arg1) | ||||
| { | ||||
| 	if(!objectBrowser) | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
| #include "resourceExtractor/ResourceConverter.h" | ||||
|  | ||||
| class CMap; | ||||
| class ObjectBrowser; | ||||
| class ObjectBrowserProxyModel; | ||||
| class CGObjectInstance; | ||||
|  | ||||
| namespace Ui | ||||
| @@ -74,8 +74,6 @@ private slots: | ||||
|  | ||||
| 	void on_toolErase_clicked(); | ||||
|  | ||||
| 	void on_treeView_activated(const QModelIndex &index); | ||||
|  | ||||
| 	void on_terrainFilterCombo_currentTextChanged(const QString &arg1); | ||||
|  | ||||
| 	void on_filter_textChanged(const QString &arg1); | ||||
| @@ -113,7 +111,7 @@ public slots: | ||||
| 	void displayStatus(const QString& message, int timeout = 2000); | ||||
|  | ||||
| private: | ||||
| 	void preparePreview(const QModelIndex &index, bool createNew); | ||||
| 	void preparePreview(const QModelIndex & index); | ||||
| 	void addGroupIntoCatalog(const std::string & groupName, bool staticOnly); | ||||
| 	void addGroupIntoCatalog(const std::string & groupName, bool useCustomName, bool staticOnly, int ID); | ||||
| 	 | ||||
| @@ -133,7 +131,7 @@ private: | ||||
|  | ||||
| private: | ||||
|     Ui::MainWindow * ui; | ||||
| 	ObjectBrowser * objectBrowser = nullptr; | ||||
| 	ObjectBrowserProxyModel * objectBrowser = nullptr; | ||||
| 	QGraphicsScene * scenePreview; | ||||
| 	 | ||||
| 	QString filename; | ||||
|   | ||||
| @@ -303,7 +303,7 @@ | ||||
|           <widget class="QLineEdit" name="filter"/> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QTreeView" name="treeView"> | ||||
|           <widget class="ObjectBrowser" name="treeView"> | ||||
|            <property name="sizePolicy"> | ||||
|             <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> | ||||
|              <horstretch>0</horstretch> | ||||
| @@ -319,8 +319,11 @@ | ||||
|            <property name="editTriggers"> | ||||
|             <set>QAbstractItemView::NoEditTriggers</set> | ||||
|            </property> | ||||
|            <property name="showDropIndicator" stdset="0"> | ||||
|             <bool>false</bool> | ||||
|            </property> | ||||
|            <property name="dragDropMode"> | ||||
|             <enum>QAbstractItemView::NoDragDrop</enum> | ||||
|             <enum>QAbstractItemView::DragOnly</enum> | ||||
|            </property> | ||||
|            <property name="selectionBehavior"> | ||||
|             <enum>QAbstractItemView::SelectItems</enum> | ||||
| @@ -1206,6 +1209,11 @@ | ||||
|    <extends>QGraphicsView</extends> | ||||
|    <header>mapview.h</header> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>ObjectBrowser</class> | ||||
|    <extends>QTreeView</extends> | ||||
|    <header>objectbrowser.h</header> | ||||
|   </customwidget> | ||||
|  </customwidgets> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include "mainwindow.h" | ||||
| #include <QGraphicsSceneMouseEvent> | ||||
| #include "mapcontroller.h" | ||||
| #include "../lib/mapObjects/CObjectClassesHandler.h" | ||||
|  | ||||
| MinimapView::MinimapView(QWidget * parent): | ||||
| 	QGraphicsView(parent) | ||||
| @@ -64,12 +65,10 @@ MapView::MapView(QWidget * parent): | ||||
|  | ||||
| void MapView::cameraChanged(const QPointF & pos) | ||||
| { | ||||
| 	//ui->mapView->translate(pos.x(), pos.y()); | ||||
| 	horizontalScrollBar()->setValue(pos.x()); | ||||
| 	verticalScrollBar()->setValue(pos.y()); | ||||
| } | ||||
|  | ||||
|  | ||||
| void MapView::setController(MapController * ctrl) | ||||
| { | ||||
| 	controller = ctrl; | ||||
| @@ -85,7 +84,12 @@ void MapView::mouseMoveEvent(QMouseEvent *mouseEvent) | ||||
|  | ||||
| 	auto pos = mapToScene(mouseEvent->pos()); //TODO: do we need to check size? | ||||
| 	int3 tile(pos.x() / 32, pos.y() / 32, sc->level); | ||||
|  | ||||
| 	 | ||||
| 	//if scene will be scrolled without mouse movement, selection, object moving and rubber band will not be updated | ||||
| 	//to change this behavior, all this logic should be placed in viewportEvent | ||||
| 	if(rubberBand) | ||||
| 		rubberBand->setGeometry(QRect(mapFromScene(mouseStart), mouseEvent->pos()).normalized()); | ||||
| 	 | ||||
| 	if(tile == tilePrev) //do not redraw | ||||
| 		return; | ||||
|  | ||||
| @@ -161,13 +165,7 @@ void MapView::mouseMoveEvent(QMouseEvent *mouseEvent) | ||||
|  | ||||
| 		if(sh.x || sh.y) | ||||
| 		{ | ||||
| 			if(sc->selectionObjectsView.newObject) | ||||
| 			{ | ||||
| 				sc->selectionObjectsView.shift = QPoint(tile.x, tile.y); | ||||
| 				sc->selectionObjectsView.selectObject(sc->selectionObjectsView.newObject); | ||||
| 				sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT; | ||||
| 			} | ||||
| 			else if(mouseEvent->buttons() & Qt::LeftButton) | ||||
| 			if(!sc->selectionObjectsView.newObject && (mouseEvent->buttons() & Qt::LeftButton)) | ||||
| 			{ | ||||
| 				if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::SELECTION) | ||||
| 				{ | ||||
| @@ -296,6 +294,11 @@ void MapView::mousePressEvent(QMouseEvent *event) | ||||
| 				{ | ||||
| 					sc->selectionObjectsView.clear(); | ||||
| 					sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::SELECTION; | ||||
| 					 | ||||
| 					if(!rubberBand) | ||||
| 						rubberBand = new QRubberBand(QRubberBand::Rectangle, this); | ||||
| 					rubberBand->setGeometry(QRect(mapFromScene(mouseStart), QSize())); | ||||
| 					rubberBand->show(); | ||||
| 				} | ||||
| 			} | ||||
| 			sc->selectionObjectsView.shift = QPoint(0, 0); | ||||
| @@ -314,6 +317,9 @@ void MapView::mouseReleaseEvent(QMouseEvent *event) | ||||
| 	auto * sc = static_cast<MapScene*>(scene()); | ||||
| 	if(!sc || !controller->map()) | ||||
| 		return; | ||||
| 	 | ||||
| 	if(rubberBand) | ||||
| 		rubberBand->hide(); | ||||
|  | ||||
| 	switch(selectionTool) | ||||
| 	{ | ||||
| @@ -324,19 +330,7 @@ void MapView::mouseReleaseEvent(QMouseEvent *event) | ||||
| 		bool tab = false; | ||||
| 		if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::MOVEMENT) | ||||
| 		{ | ||||
| 			if(sc->selectionObjectsView.newObject) | ||||
| 			{ | ||||
| 				QString errorMsg; | ||||
| 				if(controller->canPlaceObject(sc->level, sc->selectionObjectsView.newObject, errorMsg)) | ||||
| 					controller->commitObjectCreate(sc->level); | ||||
| 				else | ||||
| 				{ | ||||
| 					QMessageBox::information(this, "Can't place object", errorMsg); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 				controller->commitObjectShift(sc->level); | ||||
| 			controller->commitObjectShift(sc->level); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @@ -355,11 +349,105 @@ void MapView::mouseReleaseEvent(QMouseEvent *event) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MapView::dragEnterEvent(QDragEnterEvent * event) | ||||
| { | ||||
| 	if(!controller || !controller->map()) | ||||
| 		return; | ||||
| 	 | ||||
| 	auto * sc = static_cast<MapScene*>(scene()); | ||||
| 	if(!sc) | ||||
| 		return; | ||||
| 	 | ||||
| 	if(event->mimeData()->hasFormat("application/vcmi.object")) | ||||
| 	{ | ||||
| 		auto encodedData = event->mimeData()->data("application/vcmi.object"); | ||||
| 		QDataStream stream(&encodedData, QIODevice::ReadOnly); | ||||
| 		QVariant vdata; | ||||
| 		stream >> vdata; | ||||
| 		auto data = vdata.toJsonObject(); | ||||
| 		if(!data.empty()) | ||||
| 		{ | ||||
| 			auto preview = data["preview"]; | ||||
| 			if(preview != QJsonValue::Undefined) | ||||
| 			{ | ||||
| 				auto objId = data["id"].toInt(); | ||||
| 				auto objSubId = data["subid"].toInt(); | ||||
| 				auto templateId = data["template"].toInt(); | ||||
| 				auto factory = VLC->objtypeh->getHandlerFor(objId, objSubId); | ||||
| 				auto templ = factory->getTemplates()[templateId]; | ||||
| 				controller->discardObject(sc->level); | ||||
| 				controller->createObject(sc->level, factory->create(templ)); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		event->acceptProposedAction(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MapView::dropEvent(QDropEvent * event) | ||||
| { | ||||
| 	if(!controller || !controller->map()) | ||||
| 		return; | ||||
| 	 | ||||
| 	auto * sc = static_cast<MapScene*>(scene()); | ||||
| 	if(!sc) | ||||
| 		return; | ||||
| 	 | ||||
| 	if(sc->selectionObjectsView.newObject) | ||||
| 	{ | ||||
| 		QString errorMsg; | ||||
| 		if(controller->canPlaceObject(sc->level, sc->selectionObjectsView.newObject, errorMsg)) | ||||
| 		{ | ||||
| 			controller->commitObjectCreate(sc->level); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			controller->discardObject(sc->level); | ||||
| 			QMessageBox::information(this, "Can't place object", errorMsg); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	event->acceptProposedAction(); | ||||
| } | ||||
|  | ||||
| void MapView::dragMoveEvent(QDragMoveEvent * event) | ||||
| { | ||||
| 	auto * sc = static_cast<MapScene*>(scene()); | ||||
| 	if(!sc) | ||||
| 		return; | ||||
| 	 | ||||
| 	auto rect = event->answerRect(); | ||||
| 	auto pos = mapToScene(rect.bottomRight()); //TODO: do we need to check size? | ||||
| 	int3 tile(pos.x() / 32 + 1, pos.y() / 32 + 1, sc->level); | ||||
| 	 | ||||
| 	if(sc->selectionObjectsView.newObject) | ||||
| 	{ | ||||
| 		sc->selectionObjectsView.shift = QPoint(tile.x, tile.y); | ||||
| 		sc->selectionObjectsView.selectObject(sc->selectionObjectsView.newObject); | ||||
| 		sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT; | ||||
| 		sc->selectionObjectsView.draw(); | ||||
| 	} | ||||
| 	 | ||||
| 	event->acceptProposedAction(); | ||||
| } | ||||
|  | ||||
| void MapView::dragLeaveEvent(QDragLeaveEvent * event) | ||||
| { | ||||
| 	if(!controller || !controller->map()) | ||||
| 		return; | ||||
| 	 | ||||
| 	auto * sc = static_cast<MapScene*>(scene()); | ||||
| 	if(!sc) | ||||
| 		return; | ||||
| 	 | ||||
| 	controller->discardObject(sc->level); | ||||
| } | ||||
|  | ||||
|  | ||||
| bool MapView::viewportEvent(QEvent *event) | ||||
| { | ||||
| 	if(auto * sc = static_cast<MapScene*>(scene())) | ||||
| 	{ | ||||
| 		//auto rect = sceneRect(); | ||||
| 		auto rect = mapToScene(viewport()->geometry()).boundingRect(); | ||||
| 		controller->miniScene(sc->level)->viewport.setViewport(rect.x() / 32, rect.y() / 32, rect.width() / 32, rect.height() / 32); | ||||
| 	} | ||||
|   | ||||
| @@ -98,6 +98,10 @@ public slots: | ||||
| 	void mouseMoveEvent(QMouseEvent * mouseEvent) override; | ||||
| 	void mousePressEvent(QMouseEvent *event) override; | ||||
| 	void mouseReleaseEvent(QMouseEvent *event) override; | ||||
| 	void dragEnterEvent(QDragEnterEvent * event) override; | ||||
| 	void dragMoveEvent(QDragMoveEvent *event) override; | ||||
| 	void dragLeaveEvent(QDragLeaveEvent *event) override; | ||||
| 	void dropEvent(QDropEvent * event) override; | ||||
| 	 | ||||
| 	void cameraChanged(const QPointF & pos); | ||||
| 	 | ||||
| @@ -110,6 +114,7 @@ protected: | ||||
| 	 | ||||
| private: | ||||
| 	MapController * controller = nullptr; | ||||
| 	QRubberBand * rubberBand = nullptr; | ||||
| 	QPointF mouseStart; | ||||
| 	int3 tileStart; | ||||
| 	int3 tilePrev; | ||||
| @@ -127,7 +132,7 @@ public: | ||||
| 	 | ||||
| public slots: | ||||
| 	void mouseMoveEvent(QMouseEvent * mouseEvent) override; | ||||
| 	void mousePressEvent(QMouseEvent* event) override; | ||||
| 	void mousePressEvent(QMouseEvent * event) override; | ||||
| 	 | ||||
| signals: | ||||
| 	void cameraPositionChanged(const QPointF & newPosition); | ||||
|   | ||||
| @@ -12,12 +12,12 @@ | ||||
| #include "objectbrowser.h" | ||||
| #include "../lib/mapObjects/CObjectClassesHandler.h" | ||||
|  | ||||
| ObjectBrowser::ObjectBrowser(QObject *parent) | ||||
| ObjectBrowserProxyModel::ObjectBrowserProxyModel(QObject *parent) | ||||
| 	: QSortFilterProxyModel{parent}, terrain(Terrain::ANY_TERRAIN) | ||||
| { | ||||
| } | ||||
|  | ||||
| bool ObjectBrowser::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const | ||||
| bool ObjectBrowserProxyModel::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const | ||||
| { | ||||
| 	bool result = QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); | ||||
|  | ||||
| @@ -57,7 +57,7 @@ bool ObjectBrowser::filterAcceptsRow(int source_row, const QModelIndex & source_ | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| bool ObjectBrowser::filterAcceptsRowText(int source_row, const QModelIndex &source_parent) const | ||||
| bool ObjectBrowserProxyModel::filterAcceptsRowText(int source_row, const QModelIndex &source_parent) const | ||||
| { | ||||
| 	if(source_parent.isValid()) | ||||
| 	{ | ||||
| @@ -76,3 +76,64 @@ bool ObjectBrowser::filterAcceptsRowText(int source_row, const QModelIndex &sour | ||||
| 	return (filter.isNull() || filter.isEmpty() || item->text().contains(filter, Qt::CaseInsensitive)); | ||||
| } | ||||
|  | ||||
| Qt::ItemFlags ObjectBrowserProxyModel::flags(const QModelIndex & index) const | ||||
| { | ||||
| 	Qt::ItemFlags defaultFlags = QSortFilterProxyModel::flags(index); | ||||
|  | ||||
| 	if (index.isValid()) | ||||
| 		return Qt::ItemIsDragEnabled | defaultFlags; | ||||
| 	 | ||||
| 	return defaultFlags; | ||||
| } | ||||
|  | ||||
| QStringList ObjectBrowserProxyModel::mimeTypes() const | ||||
| { | ||||
| 	QStringList types; | ||||
| 	types << "application/vcmi.object"; | ||||
| 	return types; | ||||
| } | ||||
|  | ||||
| QMimeData * ObjectBrowserProxyModel::mimeData(const QModelIndexList & indexes) const | ||||
| { | ||||
| 	assert(indexes.size() == 1); | ||||
| 	 | ||||
| 	auto * standardModel = qobject_cast<QStandardItemModel*>(sourceModel()); | ||||
| 	assert(standardModel); | ||||
| 	 | ||||
| 	QModelIndex index = indexes.front(); | ||||
| 	QByteArray encodedData; | ||||
|  | ||||
| 	QDataStream stream(&encodedData, QIODevice::WriteOnly); | ||||
| 	 | ||||
| 	if(!index.isValid()) | ||||
| 		return nullptr; | ||||
| 	 | ||||
| 	auto text = standardModel->itemFromIndex(mapToSource(index))->data(); | ||||
| 	stream << text; | ||||
|  | ||||
| 	QMimeData * mimeData = new QMimeData; | ||||
| 	mimeData->setData("application/vcmi.object", encodedData); | ||||
| 	return mimeData; | ||||
| } | ||||
|  | ||||
| ObjectBrowser::ObjectBrowser(QWidget * parent): | ||||
| 	QTreeView(parent) | ||||
| { | ||||
| 	setDropIndicatorShown(false); | ||||
| } | ||||
|  | ||||
| void ObjectBrowser::startDrag(Qt::DropActions supportedActions) | ||||
| { | ||||
| 	QDrag *drag = new QDrag(this); | ||||
| 	auto indexes = selectedIndexes(); | ||||
| 	if(indexes.isEmpty()) | ||||
| 		return; | ||||
| 	 | ||||
| 	QMimeData * mimeData = model()->mimeData(indexes); | ||||
| 	if(!mimeData) | ||||
| 		return; | ||||
| 		 | ||||
| 	drag->setMimeData(mimeData); | ||||
|  | ||||
| 	Qt::DropAction dropAction = drag->exec(); | ||||
| } | ||||
|   | ||||
| @@ -13,10 +13,16 @@ | ||||
| #include <QSortFilterProxyModel> | ||||
| #include "../lib/Terrain.h" | ||||
|  | ||||
| class ObjectBrowser : public QSortFilterProxyModel | ||||
| class ObjectBrowserProxyModel : public QSortFilterProxyModel | ||||
| { | ||||
| public: | ||||
| 	explicit ObjectBrowser(QObject *parent = nullptr); | ||||
| 	explicit ObjectBrowserProxyModel(QObject *parent = nullptr); | ||||
| 	 | ||||
| 	Qt::ItemFlags flags(const QModelIndex &index) const override; | ||||
| 	 | ||||
| 	QStringList mimeTypes() const override; | ||||
| 	 | ||||
| 	QMimeData * mimeData(const QModelIndexList & indexes) const override; | ||||
|  | ||||
| 	TerrainId terrain; | ||||
| 	QString filter; | ||||
| @@ -25,3 +31,12 @@ protected: | ||||
| 	bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override; | ||||
| 	bool filterAcceptsRowText(int source_row, const QModelIndex &source_parent) const; | ||||
| }; | ||||
|  | ||||
| class ObjectBrowser : public QTreeView | ||||
| { | ||||
| public: | ||||
| 	ObjectBrowser(QWidget * parent); | ||||
| 	 | ||||
| protected: | ||||
| 	void startDrag(Qt::DropActions supportedActions) override; | ||||
| }; | ||||
|   | ||||
| @@ -390,7 +390,7 @@ void SelectionObjectsLayer::draw() | ||||
| 		//show translation | ||||
| 		if(selectionMode == SelectionMode::MOVEMENT && (shift.x() || shift.y())) | ||||
| 		{ | ||||
| 			painter.setOpacity(0.5); | ||||
| 			painter.setOpacity(0.7); | ||||
| 			auto newPos = QPoint(obj->getPosition().x, obj->getPosition().y) + shift; | ||||
| 			handler->drawObjectAt(painter, obj, newPos.x(), newPos.y()); | ||||
| 		} | ||||
|   | ||||
| @@ -144,7 +144,6 @@ public: | ||||
| 	void deselectObject(CGObjectInstance *); | ||||
| 	bool isSelected(const CGObjectInstance *) const; | ||||
| 	std::set<CGObjectInstance*> getSelection() const; | ||||
| 	void moveSelection(int x, int y); | ||||
| 	void clear(); | ||||
| 		 | ||||
| 	QPoint shift; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user