IPL库是一个模块化图像处理框架,支持动态加载算法、可视化流程编辑和跨平台运行。其核心设计围绕以下目标:
-
扩展性:通过插件机制添加新算法。
-
灵活性:支持多数据类型(图像、矩阵、关键点等)。
-
用户友好:提供GUI配置参数和实时预览。
核心组件及关系
1 核心类
类名 | 职责 | 关键方法/特性 |
---|---|---|
IPLProcessProperty | 管理算法参数(如阈值、颜色) | - 类型安全(Int/Double/String等) - 序列化支持 - 绑定GUI控件 |
IPLProcess | 算法基类(如滤波、边缘检测) | - 定义输入/输出 - 处理逻辑( processInputData )- 事件通知(进度/属性变更) |
IPLData | 数据容器基类(图像、矩阵等) | - 多态数据存储 - 类型标记( IPLDataType )- 数据转换( toImage() 等) |
2 关联梳理
IPLProcess类
IPLProcess
是ImagePlay框架中所有图像处理算法的抽象基类,定义了算法的统一接口和行为规范。其核心职责包括:
-
算法生命周期管理(初始化、执行、销毁)
-
数据流控制(输入/输出接口)
-
参数管理(动态属性系统)
-
事件通知(进度、状态变更)
关键设计要素
1 算法分类与扩展支持
enum IPLProcessCategory {
CATEGORY_IO, CATEGORY_EDGES, CATEGORY_FOURIER // ...共13个分类
};
enum IPLOpenCVSupport {
OPENCV_NONE, OPENCV_OPTIONAL, OPENCV_ONLY
};
-
分类系统:通过枚举明确算法类型,便于GUI按功能组织(如边缘检测、几何变换)。
-
OpenCV集成:标记算法对OpenCV的依赖程度,指导运行时资源加载。
2 算法生命周期方法
方法 | 调用时机 | 典型实现内容 |
---|---|---|
init() | 算法实例化后 | 初始化内部状态、注册参数(addProcessPropertyXxx )、定义输入/输出类型 |
processInputData() | 处理输入数据时 | 核心算法逻辑,读取参数(getProcessPropertyXxx )并生成结果 |
destroy() | 算法销毁前 | 释放GPU内存等资源 |
before/afterProcessing() | 处理前后钩子 | 数据预处理/后处理,统计计时等 |
3 数据流管理
std::vector<IPLProcessIO> _inputs, _outputs;
void addInput(std::string name, IPLDataType type);
-
动态接口:算法运行时声明所需的输入/输出数量和类型(如单输入单输出、多输入等)。
-
类型安全:通过
IPLDataType
确保数据兼容性。
属性系统详解
1 属性类型支持
void addProcessPropertyDouble("sigma", "Sigma", "Blur strength", 1.0);
double val = getProcessPropertyDouble("sigma");
-
全类型覆盖:支持从基本类型(int/bool)到复杂类型(vector/color/point)。
-
元数据绑定:每个属性关联标题、描述、取值范围,直接驱动GUI生成控件。
2 属性与GUI的联动
void notifyPropertyChangedEventHandler(); // 属性修改时触发GUI更新
-
观察者模式:属性变化自动通知界面,实现实时参数调整。
3 序列化支持
std::string toJson(); // 序列化所有属性
-
流程保存/加载:将算法配置(含参数值)导出为JSON,支持持久化。
事件与消息机制
1 进度通知
notifyProgressEventHandler(50); // 更新进度条至50%
-
用途:长时间算法运行时反馈进度。
2 错误处理
addError("Invalid input size");
if (hasErrors()) { /* 停止流程 */ }
-
多级消息:支持错误/警告/信息分级,可在GUI中差异化显示。
线程安全与状态管理
std::mutex _messageMutex; // 保护消息队列
bool _resultReady; // 标记结果有效性
-
临界区保护:消息队列的线程安全访问。
-
状态标记:通过
_updateNeeded
等标志控制算法执行逻辑。
插件系统集成
static const std::string server_name() {return "IPLProcessServer";}
-
插件契约:通过静态方法声明插件接口,动态库需实现此服务名称。
总结
设计亮点
-
开闭原则:通过派生类扩展算法,无需修改框架。
-
自描述性:属性元数据(标题/描述)减少硬编码GUI逻辑。
-
跨平台支持:纯虚接口与Qt/OpenCV解耦。
IPLProcess
通过以下设计成为框架核心:
-
标准化接口:统一算法开发范式。
-
动态灵活性:运行时可扩展的属性和数据接口。
-
生态集成:与Qt/OpenCV深度协作,同时保持独立性。
-
用户友好:丰富的元数据和事件机制支撑GUI交互。
其设计模式组合(工厂、观察者、策略模式)和严谨的接口定义,使其成为图像处理流水线的高效抽象层
算子实例
如IPLRotate 派生算子类,继承自 IPLClonableProcess<IPLRotate>
模板类,实现图像的旋转和缩放变换,自动获得克隆能力。
算子设计亮点特色
-
CRTP模式:通过模板继承实现多态克隆,避免虚函数开销。
-
OpenCV依赖:明确声明
OPENCV_ONLY
,强制使用OpenCV实现。
///头文件
class IPLSHARED_EXPORT IPLRotate : public IPLClonableProcess<IPLRotate>
{
public:
IPLRotate() : IPLClonableProcess() { init(); }
~IPLRotate() { destroy(); }
void init ();
void destroy ();
bool processInputData (IPLData*, int, bool useOpenCV);
IPLData* getResultData (int);
protected:
IPLImage* _result;
};
///-------cpp----------
void IPLRotate::init()
{
// init
_result = NULL;
// basic settings
setClassName("IPLRotate");
setTitle("Rotate/Zoom Image");
setCategory(IPLProcess::CATEGORY_GEOMETRY);
setOpenCVSupport(IPLProcess::OPENCV_ONLY);
// inputs and outputs
addInput("Image", IPL_IMAGE_COLOR);
addOutput("Image", IPL_IMAGE_COLOR);
// properties
addProcessPropertyInt("angle", "Angle", "", 0, IPL_WIDGET_SLIDER, -180, 180);
addProcessPropertyDouble("scale", "Scaling", "", 1.0, IPL_WIDGET_SLIDER, 0.1, 10.0);
addProcessPropertyPoint("center", "Center", "", IPLPoint(0,0), IPL_WIDGET_POINT);
addProcessPropertyInt("interpolation", "Interpolation:Nearest|Linear|Area|Cubic|Lanczos4", "", 0, IPL_WIDGET_COMBOBOX, 0, 4);
}
void IPLRotate::destroy()
{
delete _result;
}
bool IPLRotate::processInputData(IPLData* data, int, bool)
{
IPLImage* image = data->toImage();
// delete previous result
delete _result;
_result = NULL;
// get properties
int angle = getProcessPropertyInt("angle");
double scale = getProcessPropertyDouble("scale");
int interpolation = getProcessPropertyInt("interpolation");
IPLPoint center = getProcessPropertyPoint("center");
// Compute a rotation matrix with respect to the center of the image
//cv::Point centerPoint = cv::Point( image->width()/2, image->height()/2 );
cv::Point centerPoint = cv::Point(center.x(), center.y());
/*std::stringstream s;
s << "<b>Original Aspect Ratio</b>: " << aspectRatio << "\n";
s << "<b>New Aspect Ratio</b>: " << newAspectRatio << "\n";
s << "<b>Height</b>: " << height << "\n";
s << "<b>Width</b>: " << width;
addInformation(s.str());*/
_result = new IPLImage(image->type(), image->width(), image->height());
cv::Mat result;
// Get the rotation matrix with the specifications above
cv::Mat rot_mat = getRotationMatrix2D(centerPoint, angle, scale);
notifyProgressEventHandler(-1);
// Rotate the warped image
cv::warpAffine(image->toCvMat(), result, rot_mat, result.size(), interpolation);
delete _result;
_result = new IPLImage(result);
return true;
}
IPLData* IPLRotate::getResultData(int)
{
return _result;
}
IPLData
类
IPLData
是ImagePlay框架中所有图像处理数据的抽象基类,作为算法间传递数据的统一容器。其核心职责是:
-
多态数据封装:通过派生类支持多种数据类型(图像、矩阵、关键点等)。
-
类型安全转换:提供显式的类型检查和转换接口。
-
轻量级接口:仅保留最小必要方法,确保扩展性。
关键设计解析
1 类型系统
IPLDataType _type; // 数据类型标记(如IPL_IMAGE/IPL_MATRIX)
-
作用:运行时识别具体数据类型,避免动态转换失败。
-
典型类型(假设的枚举值):
enum IPLDataType { IPL_IMAGE_BW = 0, IPL_IMAGE_GRAYSCALE, IPL_IMAGE_COLOR, IPL_IMAGE_ORIENTED, IPL_IMAGE_COMPLEX, IPL_POINT, IPL_MATRIX, IPL_SHAPES, IPL_UNDEFINED, //Add additional data types here //... IPL_KEYPOINTS, IPL_CV_MAT, IPL_VECTOR, IPL_NUM_DATATYPES }; IPLSHARED_EXPORT const char *dataTypeName(IPLDataType type);
2 类型转换接口
virtual IPLImage* toImage(); // 转换为图像(派生类需实现)
-
设计特点:
-
非纯虚函数:基类提供默认实现(可能返回
nullptr
或抛异常),允许部分派生类不实现全部转换。 -
显式转换:强制开发者明确处理类型差异,比隐式转换更安全。
-
3 类型兼容性检查
bool isConvertibleTo(IPLDataType target);
-
用途:在转换前检查合法性,例如:
if (data->isConvertibleTo(IPL_IMAGE)) { IPLImage* img = data->toImage(); }
派生类实现示例
1 图像数据(IPLImage
)
class IPLSHARED_EXPORT IPLImage : public IPLData
{
public:
IPLImage();
IPLImage( const IPLImage& image );
IPLImage( IPLDataType _type, int width, int height );
IPLImage( cv::Mat& cvMat );
~IPLImage();
int getNumberOfPlanes( void ) { return _nrOfPlanes; }
int width(void) { return _width; }
int height(void) { return _height; }
uchar* rgb32 (void);
static void rgb32CleanupHandler(void *info);
IPLImagePlane* plane(int planeNr);
void fillColor( ipl_basetype color );
std::string toString(int x, int y);
cv::Mat toCvMat();
protected:
int _width;
int _height;
int _nrOfPlanes;
std::vector<uchar> _rgb32;
static int _instanceCount;
std::vector<IPLImagePlane*> _planes;
};
2 矩阵数据(IPLMatrix
)
class IPLSHARED_EXPORT IPLMatrix : public IPLData
{
public:
IPLMatrix (int height, int width);
IPLMatrix (int height, int width, ipl_basetype array[]);
IPLMatrix (const IPLMatrix& other);
~IPLMatrix ();
ipl_basetype get (int x, int y);
ipl_basetype get (int i);
void set (int x, int y, ipl_basetype value);
void set (int i, ipl_basetype value);
int height () { return _height; }
int width () { return _width; }
int size () { return _height * _width; }
protected:
int _width;
int _height;
std::vector<ipl_basetype> _data;
};
典型使用场景
1 算法数据处理
bool EdgeDetectionProcess::processInputData(IPLData* data) {
IPLImage* img = data->toImage();
if (!img) {
addError("Input must be an image");
return false;
}
// ...处理逻辑...
}
2 多类型支持
void DisplayData(IPLData* data) {
switch(data->type()) {
case IPL_IMAGE: renderImage(data->toImage()); break;
case IPL_POINT: drawPoint(data->toPoint()); break;
// ...其他类型...
}
}
总结
IPLData
通过简洁的接口设计实现了:
-
统一数据容器:屏蔽不同数据类型的差异。
-
安全类型转换:通过显式接口降低错误风险。
-
框架可扩展性:为新增数据类型提供标准接入点。
其设计体现了“单一职责”和“开闭原则”,是IPL库数据流处理的核心基石。通过引入现代C++特性(如智能指针、类型推导),可进一步提升易用性和安全性。
IPLProcessProperty类
IPLProcessProperty
是ImagePlay框架中算法参数的基类,负责:
-
统一管理各种类型的算法参数(整型、浮点型、字符串等)
-
绑定GUI控件与参数交互(滑动条、颜色选择器等)
-
支持序列化用于保存/加载算法配置
典型派生类对比
类型 | 存储值 | 典型用途 | GUI控件 |
---|---|---|---|
IPLProcessPropertyInt | int | 阈值、核大小 | 滑动条 |
IPLProcessPropertyDouble | double | 标准差、缩放比例 | 带小数点的滑动条 |
IPLProcessPropertyBool | bool | 开关选项 | 复选框 |
IPLProcessPropertyColor | IPLColor | 画笔颜色、ROI标记色 | 颜色选择器 |
IPLProcessPropertyString | std::string | 文件路径、文本输入 | 文本框 |
详见算子属性
算子调用管理及显示
IPProcessFactory类
IPProcessFactory
是ImagePlay框架中的算法工厂类,采用工厂模式实现:
-
集中管理所有图像处理算法(如滤波、边缘检测等)
-
动态注册和实例化算法对象
-
分类检索算法(按边缘检测/几何变换等类别)
class IPProcessFactory
{
public:
IPProcessFactory ();
~IPProcessFactory ();
void registerProcess (QString name, IPLProcess* getInstance);
void unregisterProcess (QString name);
IPLProcess* getInstance (QString name);
QStringList getProcessNamesByCategory (IPLProcess::IPLProcessCategory category);
private:
QMap<QString, IPLProcess*> _map; //!< Contains all currently registered IPLProcesses by name
};
///---cpp----------
#include "IPProcessFactory.h"
IPProcessFactory::IPProcessFactory()
{
}
IPProcessFactory::~IPProcessFactory()
{
// delete all template instances
/* for(QMap<QString, IPLProcess*>::iterator it = _map.begin(); it != _map.end(); it++)
{
IPLProcess* p = it.value();
delete p;
}*/
}
void IPProcessFactory::registerProcess(QString name, IPLProcess *process)
{
qDebug() << "IPProcessFactory::registerProcess: " << name << " -> " << process;
_map.insert(name, process);
}
void IPProcessFactory::unregisterProcess(QString name)
{
qDebug() << "IPProcessFactory::unregisterProcess: " << name;
if(_map.contains(name))
{
// delete instance and remove from map
delete _map.value(name);
_map.remove(name);
}
}
IPLProcess* IPProcessFactory::getInstance(QString name)
{
qDebug() << "IPProcessFactory::getInstance: " << name;
if(_map.contains(name))
{
// return a fresh copy of the template process
IPLProcess* process = _map.value(name)->clone();
process->properties()->clear();
process->inputs()->clear();
process->outputs()->clear();
process->init();
return process;
}
else
{
return NULL;
}
}
QStringList IPProcessFactory::getProcessNamesByCategory(IPLProcess::IPLProcessCategory category)
{
qDebug() << "IPProcessFactory::getProcessNamesByCategory";
QStringList filteredList;
for (auto it = _map.begin(); it != _map.end(); ++it)
{
if(it.value()->category() == category)
{
filteredList.push_back(it.key());
}
}
return filteredList;
}
UI显示
主界面加载及注册
void MainWindow::loadProcesses()
{
// we need a process factory to instanciate at runtime from string
_factory = new IPProcessFactory;
// register all processes to the factory
_factory->registerProcess("IPLConvertToGray", new IPLConvertToGray);
_factory->registerProcess("IPLConvertToColor", new IPLConvertToColor);
_factory->registerProcess("IPLBinarize", new IPLBinarize);
_factory->registerProcess("IPLLoadImage", new IPLLoadImage);
_factory->registerProcess("IPLCamera", new IPLCamera);
//_factory->registerProcess("IPLLoadVideo", new IPLLoadVideo);
_factory->registerProcess("IPLLoadImageSequence", new IPLLoadImageSequence);
_factory->registerProcess("IPLSaveImage", new IPLSaveImage);
_factory->registerProcess("IPLSplitPlanes", new IPLSplitPlanes);
_factory->registerProcess("IPLMergePlanes", new IPLMergePlanes);
_factory->registerProcess("IPLGaussianLowPass", new IPLGaussianLowPass);
_factory->registerProcess("IPLGammaCorrection", new IPLGammaCorrection);
_factory->registerProcess("IPLConvolutionFilter", new IPLConvolutionFilter);
_factory->registerProcess("IPLMorphologyBinary", new IPLMorphologyBinary);
_factory->registerProcess("IPLMorphologyGrayscale", new IPLMorphologyGrayscale);
_factory->registerProcess("IPLMorphologyHitMiss", new IPLMorphologyHitMiss);
_factory->registerProcess("IPLBlendImages", new IPLBlendImages);
_factory->registerProcess("IPLArithmeticOperations",new IPLArithmeticOperations);
_factory->registerProcess("IPLArithmeticOperationsConstant", new IPLArithmeticOperationsConstant);
_factory->registerProcess("IPLSynthesize", new IPLSynthesize);
_factory->registerProcess("IPLFlipImage", new IPLFlipImage);
_factory->registerProcess("IPLGradientOperator", new IPLGradientOperator);
// TODO: Fix algorithm and add again.
_factory->registerProcess("IPLRandomPoint", new IPLRandomPoint);
_factory->registerProcess("IPLCanvasSize", new IPLCanvasSize);
_factory->registerProcess("IPLResize", new IPLResize);
_factory->registerProcess("IPLRotate", new IPLRotate);
_factory->registerProcess("IPLEnhanceMode", new IPLEnhanceMode);
_factory->registerProcess("IPLFillConcavities", new IPLFillConcavities);
_factory->registerProcess("IPLGabor", new IPLGabor);
_factory->registerProcess("IPLInverseContrastRatioMapping",new IPLInverseContrastRatioMapping);
_factory->registerProcess("IPLMax", new IPLMax);
_factory->registerProcess("IPLMaxMinMedian", new IPLMaxMinMedian);
_factory->registerProcess("IPLMedian", new IPLMedian);
_factory->registerProcess("IPLCanny", new IPLCanny);
_factory->registerProcess("IPLHoughCircles", new IPLHoughCircles);
_factory->registerProcess("IPLHarrisCorner", new IPLHarrisCorner);
_factory->registerProcess("IPLExtractLines", new IPLExtractLines);
_factory->registerProcess("IPLExtrema", new IPLExtrema);
_factory->registerProcess("IPLLaplaceOfGaussian", new IPLLaplaceOfGaussian);
_factory->registerProcess("IPLMin", new IPLMin);
_factory->registerProcess("IPLMorphologicalEdge", new IPLMorphologicalEdge);
_factory->registerProcess("IPLNormalizeIllumination",new IPLNormalizeIllumination);
_factory->registerProcess("IPLBinarizeSavola", new IPLBinarizeSavola);
_factory->registerProcess("IPLOnePixelEdge", new IPLOnePixelEdge);
_factory->registerProcess("IPLRankTransform", new IPLRankTransform);
_factory->registerProcess("IPLUnsharpMasking", new IPLUnsharpMasking);
_factory->registerProcess("IPLCompassMask", new IPLCompassMask);
_factory->registerProcess("IPLTriangleSegmentation",new IPLTriangleSegmentation);
_factory->registerProcess("IPLStretchContrast", new IPLStretchContrast);
_factory->registerProcess("IPLNegate", new IPLNegate);
_factory->registerProcess("IPLMarkImage", new IPLMarkImage);
_factory->registerProcess("IPLLocalThreshold", new IPLLocalThreshold);
_factory->registerProcess("IPLHysteresisThreshold", new IPLHysteresisThreshold);
_factory->registerProcess("IPLFalseColor", new IPLFalseColor);
_factory->registerProcess("IPLEqualizeHistogram", new IPLEqualizeHistogram);
_factory->registerProcess("IPLBinarizeUnimodal", new IPLBinarizeUnimodal);
_factory->registerProcess("IPLBinarizeOtsu", new IPLBinarizeOtsu);
_factory->registerProcess("IPLBinarizeKMeans", new IPLBinarizeKMeans);
_factory->registerProcess("IPLBinarizeEntropy", new IPLBinarizeEntropy);
_factory->registerProcess("IPLAddNoise", new IPLAddNoise);
_factory->registerProcess("IPLFFT", new IPLFFT);
_factory->registerProcess("IPLIFFT", new IPLIFFT);
_factory->registerProcess("IPLFrequencyFilter", new IPLFrequencyFilter);
_factory->registerProcess("IPLLabelBlobs", new IPLLabelBlobs);
_factory->registerProcess("IPLAccumulate", new IPLAccumulate);
_factory->registerProcess("IPLHoughLines", new IPLHoughLines);
_factory->registerProcess("IPLHoughLineSegments", new IPLHoughLineSegments);
_factory->registerProcess("IPLUndistort", new IPLUndistort);
_factory->registerProcess("IPLWarpAffine", new IPLWarpAffine);
_factory->registerProcess("IPLWarpPerspective", new IPLWarpPerspective);
_factory->registerProcess("IPLGoodFeaturesToTrack", new IPLGoodFeaturesToTrack);
// not ready:
/*_factory->registerProcess("IPLMatchTemplate", new IPLMatchTemplate);
_factory->registerProcess("IPLFloodFill", new IPLFloodFill);
_factory->registerProcess("IPLOpticalFlow", new IPLOpticalFlow);
_factory->registerProcess("IPProcessScript", new IPProcessScript);
_factory->registerProcess("IPLFeatureDetection", new IPLFeatureDetection);
_factory->registerProcess("IPLFeatureMatcher", new IPLFeatureMatcher);
_factory->registerProcess("IPLCameraCalibration", new IPLCameraCalibration);*/
}
算子列表UI呈现
void IPProcessListTabWidget::init(MainWindow *mainWindow)
{
_mainWindow = mainWindow;
clear();
// items
QStringList categoryIcons;
categoryIcons.append(":/icons/16.png");
categoryIcons.append(":/icons/12.png");
categoryIcons.append(":/icons/27.png");
categoryIcons.append(":/icons/26.png");
categoryIcons.append(":/icons/26.png");
categoryIcons.append(":/icons/8.png");
categoryIcons.append(":/icons/8.png");
categoryIcons.append(":/icons/8.png");
categoryIcons.append(":/icons/8.png");
categoryIcons.append(":/icons/8.png");
categoryIcons.append(":/icons/8.png");
categoryIcons.append(":/icons/8.png");
QStringList processCategories; // CATEGORY_UNDEFINED
processCategories.append("Input/Output"); // CATEGORY_IO
processCategories.append("Conversions"); // CATEGORY_CONVERSIONS
processCategories.append("Geometry"); // CATEGORY_GEOMETRY
processCategories.append("Arithmetic Operations"); // CATEGORY_ARITHMETIC
processCategories.append("Point Operations"); // CATEGORY_POINTOPERATIONS
processCategories.append("Local Operations"); // CATEGORY_LOCALOPERATIONS
processCategories.append("Morphology & Rank Order");// CATEGORY_MORPHOLOGY
processCategories.append("Histogram"); // CATEGORY_HISTOGRAM
processCategories.append("Edges"); // CATEGORY_GRADIENTS
processCategories.append("Gradients"); // CATEGORY_GRADIENTS
processCategories.append("Fourier"); // CATEGORY_FOURIER
processCategories.append("Objects"); // CATEGORY_OBJECTS
processCategories.append("Plugins"); //
//list process names by process category
QList<QStringList> processLibrary;
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_IO));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_CONVERSIONS));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_GEOMETRY));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_ARITHMETIC));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_POINTOPERATIONS));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_LOCALOPERATIONS));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_MORPHOLOGY));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_HISTOGRAM));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_EDGES));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_GRADIENTS));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_FOURIER));
processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_OBJECTS));
QStringList plugins;
for(int i=0; i<mainWindow->pluginManager()->loadedPlugins()->size(); i++)
{
plugins.append(mainWindow->pluginManager()->loadedPlugins()->at(i));
}
processLibrary.append(plugins);
// all processes tab
_allProcessesList = new IPProcessList(mainWindow);
QWidget* tabAll = new QWidget(this);
tabAll->setLayout(new QVBoxLayout);
QLabel* labelAll = new QLabel("All Processes", tabAll);
labelAll->setStyleSheet("font-size: 12px; font-weight: bold;");
tabAll->layout()->addWidget(labelAll);
tabAll->layout()->addWidget(_allProcessesList);
// rotate icon
QPixmap pixmap(":/home.png");
QMatrix transform;
transform.rotate(90);
addTab(tabAll, QIcon(pixmap.transformed(transform)), "");
setIconSize(QSize(20, 20));
// add all other tabs
for(int i=0; i<processCategories.length(); i++)
{
QWidget* tab = new QWidget(this);
tab->setLayout(new QVBoxLayout);
QLabel* label = new QLabel(processCategories[i], tab);
label->setStyleSheet("font-size: 12px; font-weight: bold;");
IPProcessList* list = new IPProcessList(mainWindow, this);
QPixmap categoryIcon;
for(int j=0; j < processLibrary[i].length(); j++)
{
QString processID = processLibrary[i].at(j);
IPLProcess* tmpProcess = mainWindow->factory()->getInstance(processID);
// only add if instance exists
if(tmpProcess)
{
QString title = QString::fromStdString(tmpProcess->title());
QString keywords = QString::fromStdString(tmpProcess->keywords());
// add to list
list->addProcessItem(processID, title, keywords, tmpProcess->category());
// and add to all processes list
_allProcessesList->addProcessItem(processID, title, keywords, tmpProcess->category());
// use icon of first process for the category tab
if(categoryIcon.width() == 0)
{
QFileInfo iconFile(_mainWindow->processIconPath(processID));
if(iconFile.exists())
{
categoryIcon = QPixmap(iconFile.absoluteFilePath());
}
}
}
delete tmpProcess;
}
// sort items
list->sortItems();
// add GUI elements
tab->layout()->addWidget(label);
tab->layout()->addWidget(list);
// for the last tab (plugins) add buttons
if(i == processCategories.length()-1)
{
QPushButton* btnReloadPlugins = new QPushButton("Reload Plugins");
connect(btnReloadPlugins, &QPushButton::clicked, mainWindow, &MainWindow::reloadPlugins);
tab->layout()->addWidget(btnReloadPlugins);
}
// rotate icon
//QPixmap pixmap(categoryIcons[i]);
QMatrix transform;
transform.rotate(90);
// only add categories with entries
addTab(tab, QIcon(categoryIcon.transformed(transform)), "");
setTabToolTip(i+1, processCategories[i]);
}
// set plugins tab icon
QPixmap pluginIcon(":/plugins.png");
setTabIcon(count()-1, QIcon(pluginIcon.transformed(transform)));
// sort all process list
_allProcessesList->sortItems();
}