diff --git a/addons/tabswitcher/CMakeLists.txt b/addons/tabswitcher/CMakeLists.txt --- a/addons/tabswitcher/CMakeLists.txt +++ b/addons/tabswitcher/CMakeLists.txt @@ -28,4 +28,5 @@ ############# unit tests ################ if (BUILD_TESTING) add_subdirectory(autotests) + add_subdirectory(tests) endif() diff --git a/addons/tabswitcher/tabswitcherfilesmodel.h b/addons/tabswitcher/tabswitcherfilesmodel.h --- a/addons/tabswitcher/tabswitcherfilesmodel.h +++ b/addons/tabswitcher/tabswitcherfilesmodel.h @@ -59,6 +59,10 @@ TabswitcherFilesModel(const FilenameList & data); bool insertRow(int row, FilenameListItem const * const item); bool removeRow(int row); + /** + * Clears all data from the model + */ + void clear(); int rowCount() const; /** * NOTE: The returned pointer will become invalid as soon as the underlying vector changes. diff --git a/addons/tabswitcher/tabswitcherfilesmodel.cpp b/addons/tabswitcher/tabswitcherfilesmodel.cpp --- a/addons/tabswitcher/tabswitcherfilesmodel.cpp +++ b/addons/tabswitcher/tabswitcherfilesmodel.cpp @@ -21,6 +21,7 @@ #include "tabswitcherfilesmodel.h" #include +#include #include @@ -74,14 +75,17 @@ std::for_each(data.begin(), data.end(), [prefix_length](FilenameListItem & item) { + // Note that item.documentName can contain additional characters - e.g. "README.md (2)" - + // so we cannot use that and have to parse the base filename by other means: + QFileInfo fileinfo(item.fullPath); + QString basename = fileinfo.fileName(); // e.g. "archive.tar.gz" // cut prefix (left side) and cut document name (plus slash) on the right side - int len = item.fullPath.length() - prefix_length - item.documentName.length() - 1; + int len = item.fullPath.length() - prefix_length - basename.length() - 1; if (len > 0) { // only assign in case item.fullPath is not empty - // "PREFIXPATH/REMAININGPATH/DOCUMENTNAME" --> "REMAININGPATH" + // "PREFIXPATH/REMAININGPATH/BASENAME" --> "REMAININGPATH" item.displayPathPrefix = QStringRef(&item.fullPath, prefix_length, len).toString(); } }); - } } @@ -117,6 +121,15 @@ return true; } +void detail::TabswitcherFilesModel::clear() +{ + if (data_.size() > 0) { + beginRemoveRows(QModelIndex(), 0, data_.size() - 1); + data_.clear(); + endRemoveRows(); + } +} + int detail::TabswitcherFilesModel::rowCount() const { return data_.size(); diff --git a/addons/tabswitcher/tests/CMakeLists.txt b/addons/tabswitcher/tests/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/addons/tabswitcher/tests/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.0.0) +project(tstestapp) + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) + +# Find the QtWidgets library +find_package(Qt5Widgets CONFIG REQUIRED) + +set(SRC + main.cpp + tstestapp.cpp + ../tabswitcherfilesmodel.cpp +) + +add_executable(tstestapp ${SRC}) +target_link_libraries(tstestapp Qt5::Widgets) + diff --git a/addons/tabswitcher/tests/main.cpp b/addons/tabswitcher/tests/main.cpp new file mode 100644 --- /dev/null +++ b/addons/tabswitcher/tests/main.cpp @@ -0,0 +1,11 @@ +#include "tstestapp.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + TsTestApp w; + w.show(); + + return app.exec(); +} diff --git a/addons/tabswitcher/tests/tstestapp.h b/addons/tabswitcher/tests/tstestapp.h new file mode 100644 --- /dev/null +++ b/addons/tabswitcher/tests/tstestapp.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +class TsTestApp : public QMainWindow +{ + Q_OBJECT + +public: + explicit TsTestApp(QWidget *parent = nullptr); + ~TsTestApp(); + +private: + class Impl; + std::unique_ptr impl_; +}; diff --git a/addons/tabswitcher/tests/tstestapp.cpp b/addons/tabswitcher/tests/tstestapp.cpp new file mode 100644 --- /dev/null +++ b/addons/tabswitcher/tests/tstestapp.cpp @@ -0,0 +1,112 @@ +#include "tstestapp.h" +#include "../tabswitcherfilesmodel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// https://www.fluentcpp.com/2017/09/22/make-pimpl-using-unique_ptr/ +class TsTestApp::Impl +{ +public: + void insert_1_item() + { + auto icon = QIcon::fromTheme(QLatin1String("blurimage")); + model.insertRow(0, new detail::FilenameListItem(icon, QLatin1String("abc.d"), QLatin1String("/home/user2/folder1/abc.d"))); + treeview1->resizeColumnToContents(0); + } + + void remove_1_item() + { + model.removeRow(0); + treeview1->resizeColumnToContents(0); + } + + void set_items_cutoff_bug() + { + model.clear(); + auto icon = QIcon::fromTheme(QLatin1String("document-export")); + +#define INS__(a, b) model.insertRow(model.rowCount(), new detail::FilenameListItem(icon, QLatin1String(a), QLatin1String(b))); + + INS__("multimedia-system.log", "/home/gregor/logs/notifications/multimedia-system.log") + INS__("servicemenueditor", "/home/gregor/dev/src/kservicemenueditor-0.2a/servicemenueditor") + INS__("kdesrc-build", "/home/gregor/kde/src/kdesrc-build/kdesrc-build") + INS__("README.md (3)", "/home/gregor/node_modules/autolinker/README.md") + INS__("package.json (3)", "/home/gregor/node_modules/autolinker/package.json") + INS__("LICENSE (3)", "/home/gregor/node_modules/autolinker/LICENSE") + INS__("package.json (2)", "/home/gregor/node_modules/asynckit/package.json") + + treeview1->resizeColumnToContents(0); + } + +public: + detail::TabswitcherFilesModel model; + QTreeView* treeview1; +}; + +TsTestApp::TsTestApp(QWidget *parent) : + QMainWindow(parent), + impl_(new TsTestApp::Impl) +{ + setGeometry(0, 0, 1024, 800); + setCentralWidget(new QWidget(this)); + auto l = new QVBoxLayout(); + centralWidget()->setLayout(l); + + auto hl = new QHBoxLayout(); + l->addLayout(hl); + + auto buttonInsert1 = new QPushButton(QLatin1String("Ins 1 item"), this); + connect(buttonInsert1, &QPushButton::clicked, this, [=] { impl_->insert_1_item(); }); + hl->addWidget(buttonInsert1); + + auto buttonRemove1 = new QPushButton(QLatin1String("Del 1 item"), this); + connect(buttonRemove1, &QPushButton::clicked, this, [=] { impl_->remove_1_item(); }); + hl->addWidget(buttonRemove1); + + auto buttonSetTestSet1 = new QPushButton(QLatin1String("set_items_cutoff_bug"), this); + connect(buttonSetTestSet1, &QPushButton::clicked, this, [=] { impl_->set_items_cutoff_bug(); }); + hl->addWidget(buttonSetTestSet1); + + impl_->treeview1 = new QTreeView(this); + l->addWidget(impl_->treeview1); + impl_->treeview1->setHeaderHidden(true); + impl_->treeview1->setRootIsDecorated(false); + + auto icon = QIcon::fromTheme(QLatin1String("edit-undo")); + impl_->model.insertRow(0, new detail::FilenameListItem(icon, QLatin1String("file1.h"), QLatin1String("/home/gm/projects/proj1/src/file1.h"))); + impl_->model.insertRow(0, new detail::FilenameListItem(icon, QLatin1String("file2.cpp"), QLatin1String("/home/gm/projects/proj1/src/file2.cpp"))); + impl_->model.insertRow(0, new detail::FilenameListItem(icon, QLatin1String("file3.py"), QLatin1String("/home/gm/dev/file3.py"))); + impl_->model.insertRow(0, new detail::FilenameListItem(icon, QLatin1String("file3kjaskdfkljasdfklj089asdfkjklasdjf90asdfsdfkj.py"), QLatin1String("/home/gm/dev/file3kjaskdfkljasdfklj089asdfkjklasdjf90asdfsdfkj.py"))); + impl_->model.insertRow(0, new detail::FilenameListItem(icon, QLatin1String("file3.py"), QLatin1String("/home/gm/dev/proj2/asldfkjasdfk/asdlfkjasd;faf/;ajsdkfgjaskdfgasdf/file3.py"))); + //impl_->insert_a_item(); + //impl_->remove_a_item(); + + impl_->model.rowCount(); + impl_->model.item(0); + impl_->model.index(0, 0); + + impl_->treeview1->setModel(&impl_->model); + impl_->treeview1->resizeColumnToContents(0); + impl_->treeview1->resizeColumnToContents(1); + + auto listview1 = new QListView(this); + l->addWidget(listview1); + listview1->setModel(&impl_->model); + + auto treeview2 = new QTreeView(this); + l->addWidget(treeview2); +} + +TsTestApp::~TsTestApp() +{ +}