Skip to content

Instantly share code, notes, and snippets.

@aoloe
Last active March 21, 2018 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aoloe/d98bc9ec0e88e65600908768db75ea18 to your computer and use it in GitHub Desktop.
Save aoloe/d98bc9ec0e88e65600908768db75ea18 to your computer and use it in GitHub Desktop.
cycle and reverse for scribus

Cycle and reverse

Proof of concept for improving the swap function in the Align & Distribute tool in Scribus

  • Much shorter code
  • Probably more correct
  • CycleLeft does not exactly the same as the current SwapLeft, but should be close enough and much simpler.
  • Reverse is a "real" swap.

Warning: the initial list is on purpose out of order (in Scribus AObjects is on the order of selection!).
The items are inserted as c a b, and when ordered they are indeed a b c.
The order (of selection) is kept in AObjects and you have to keep an eye on the coordinates to figure out the current order.

Links:

Trying QMultiMap

QMaps are "automatically" sorted.

I tried to use a QPoint as the key and a reference to the list's item as the value, but I could not find a way to set the value of the item in a way, that the one in the list also gets changed.

Finally, I've switched to the QList based solution in the main.cpp file.

#include <QMultiMap>
#include <QPoint>

bool operator <(QPoint a, QPoint b)
{
    return a.x() < b.x() || (a.x() == b.x() && a.y() < b.y());
}

int main()
{
    // [...]
    QMultiMap<QPoint, AObject*> def{};
    for (auto &a: aObjects) {
        def.insert({a.x, a.y}, &a);
    }
    QMutableMapIterator<QPoint, AObject*> it(def);
    it.toFront();
    it.next();
	auto swapX = it.value()->x;
    auto prevIt = it;
    it.next();
	while (it.hasNext()) {
        auto& temp = prevIt.value();
        temp->y = 20; // it does not change the items in the original list
        auto prevIt = it;
        it.next();
	}
    // [...]
}
int main()
{
    // [...]
	auto it = def.begin();
	auto swapX = it.value()->x;
	auto swapY = it.value()->y;
    auto prevIt = it;
	++it;
	while (it != def.end()) {
        prevIt.value()->y = 20; // it does not change the items in the original list

        qDebug() << prevIt.key();
        qDebug() << prevIt.value()->x;
        auto prevIt = it;
        ++it;
	}
    // [...]
}

Presentation

  • the current state
  • the new implementation
    • issues with map
      • we need qmultimap
      • how to write to the reference in the qmultimap?
    • simpler with qlist
  • algorithms?
    • iter_swap
      • std::iter_swap(it1, it2) is equivalent to std::swap(*it1, *it2)
    • reverse
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
PROJECT(cycle-and-reverse)
SET(CMAKE_CXX_STANDARD 14)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5Core)
ADD_EXECUTABLE(cycle-and-reverse
main.cpp
)
target_link_libraries(cycle-and-reverse
Qt5::Core
)
#include <QDebug>
#include <QList>
class AObject
{
public:
char t{' '};
int x{0};
int y{0};
};
class ScribusDoc
{
public:
void reverse()
{
QList<AObject*> items{};
for (auto &a: AObjects) {
items.append(&a);
}
qSort(items.begin(), items.end(), compareAObject);
auto itBegin = items.begin();
auto itEnd = --items.end();
while (itBegin < itEnd) {
auto swapX = (*itBegin)->x;
auto swapY = (*itBegin)->y;
(*itBegin)->x = (*itEnd)->x;
(*itBegin)->y = (*itEnd)->y;
(*itEnd)->x = swapX;
(*itEnd)->y = swapY;
++itBegin;
--itEnd;
}
}
void cycleRight()
{
QList<AObject*> items{};
for (auto &a: AObjects) {
items.append(&a);
}
qSort(items.begin(), items.end(), compareAObject);
auto it = items.begin();
auto swapX = (*it)->x;
auto swapY = (*it)->y;
auto prevIt = it;
++it;
while (it != items.end()) {
(*prevIt)->x = (*it)->x;
(*prevIt)->y = (*it)->y;
prevIt = it;
++it;
}
it = --items.end();
(*it)->x = swapX;
(*it)->y = swapY;
}
void render()
{
qDebug() << "-----";
for (auto a: AObjects) {
qDebug() << a.t << a.x << a.y;
}
}
private:
QList<AObject> AObjects{{'c',3,4},{'a',2,1},{'b',2,2}};
static bool compareAObject(const AObject* a, const AObject* b)
{
return a->x < b->x || (a->x == b->x && a->y < b->y);
}
};
int main()
{
ScribusDoc doc;
doc.render();
qDebug() << "a b c > c a b > b c a > a b c";
doc.cycleRight();
doc.render();
doc.cycleRight();
doc.render();
doc.cycleRight();
doc.render();
qDebug() << "a b c > c a b > a b c";
doc.reverse();
doc.render();
doc.reverse();
doc.render();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment